Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save jjaderberg/77f0eafabd01703956ce162ab71cc5cc to your computer and use it in GitHub Desktop.
Save jjaderberg/77f0eafabd01703956ce162ab71cc5cc to your computer and use it in GitHub Desktop.

Skill Match

Introduction

You have access to a network of people connected with each other, living in different locations, with various skill sets. You are looking for a suitable candidate for a job. Let’s see how a graph database can help you match the job with the people you know.

Initialize graph

CREATE

//People
(kjg:Person {name:'Karl-Johan'}),
(john:Person {name:'John'}),
(anna:Person {name:'Anna'}),
(steve:Person {name:'Steve'}),
(michael:Person {name:'Michael'}),
(asuka:Person {name:'Asuka'}),

//Skills
(xml:Skill {name:'XML'}),
(xslt:Skill {name:'XSLT'}),
(writing:Skill {name:'Writing'}),
(asciidoc:Skill {name:'asciidoc'}),
(html:Skill {name:'HTML'}),
(pdf:Skill {name:'PDF'}),
(css:Skill {name:'CSS'}),
(java:Skill {name:'Java'}),
(ruby:Skill {name:'Ruby'}),
(javascript:Skill {name:'JavaScript'}),
(neo4j:Skill {name:'Neo4j'}),
(python:Skill {name:'Python'}),
(coffeescript:Skill {name:'CoffeeScript'}),
(scala:Skill {name:'Scala'}),
(ia:Skill {name:'Information architecture'}),
(dita:Skill {name:'DITA'}),
(docbook:Skill {name:'DocBook'}),

//Cities
(malmo:City {name:'Malmo'}),
(lund:City {name:'Lund'}),
(boston:City {name:'Boston'}),
(london:City {name:'London'}),
(tokyo:City {name:'Tokyo'}),

//Job
(infodev:Job {title:'Information Developer'}),
(infodev)-[:REQUIRED_SKILL]->(writing),
(infodev)-[:REQUIRED_SKILL]->(asciidoc),
(infodev)-[:REQUIRED_SKILL]->(pdf),
(infodev)-[:REQUIRED_SKILL]->(html),
(infodev)-[:REQUIRED_SKILL]->(css),
(infodev)-[:REQUIRED_SKILL]->(java),
(infodev)-[:REQUIRED_SKILL]->(ruby),
(infodev)-[:REQUIRED_SKILL]->(javascript),
(infodev)-[:DESIRED_LOCATION]->(malmo),
(infodev)-[:DESIRED_LOCATION]->(london),
(infodev)-[:OPTIONAL_SKILL]->(neo4j),
(infodev)-[:OPTIONAL_SKILL]->(python),
(infodev)-[:OPTIONAL_SKILL]->(coffeescript),
(infodev)-[:OPTIONAL_SKILL]->(scala),
(infodev)-[:OPTIONAL_SKILL]->(xslt),

//Knowledge
(kjg)-[:KNOWS]->(xml),
(kjg)-[:KNOWS]->(xslt),
(kjg)-[:KNOWS]->(html),
(kjg)-[:KNOWS]->(pdf),
(kjg)-[:KNOWS]->(css),
(kjg)-[:KNOWS]->(java),
(kjg)-[:KNOWS]->(javascript),
(kjg)-[:KNOWS]->(ia),
(kjg)-[:KNOWS]->(dita),
(kjg)-[:KNOWS]->(docbook),
(john)-[:KNOWS]->(xml),
(john)-[:KNOWS]->(xslt),
(john)-[:KNOWS]->(java),
(john)-[:KNOWS]->(javascript),
(anna)-[:KNOWS]->(css),
(anna)-[:KNOWS]->(java),
(anna)-[:KNOWS]->(javascript),
(anna)-[:KNOWS]->(ia),
(anna)-[:KNOWS]->(dita),
(steve)-[:KNOWS]->(dita),
(steve)-[:KNOWS]->(docbook),
(michael)-[:KNOWS]->(xml),
(michael)-[:KNOWS]->(css),
(michael)-[:KNOWS]->(java),
(michael)-[:KNOWS]->(javascript),
(michael)-[:KNOWS]->(dita),
(michael)-[:KNOWS]->(docbook),
(michael)-[:KNOWS]->(python),
(michael)-[:KNOWS]->(writing),
(michael)-[:KNOWS]->(pdf),
(michael)-[:KNOWS]->(coffeescript),
(asuka)-[:KNOWS]->(html),
(asuka)-[:KNOWS]->(pdf),
(asuka)-[:KNOWS]->(css),

//Lives in
(kjg)-[:LIVES_IN]->(lund),
(john)-[:LIVES_IN]->(london),
(anna)-[:LIVES_IN]->(malmo),
(steve)-[:LIVES_IN]->(boston),
(michael)-[:LIVES_IN]->(boston),
(asuka)-[:LIVES_IN]->(tokyo),

//Relationships
(kjg)-[:CONNECTED_WITH]->(steve),
(steve)<-[:CONNECTED_WITH]-(kjg),
(john)-[:CONNECTED_WITH]->(anna),
(anna)<-[:CONNECTED_WITH]-(john),
(kjg)-[:CONNECTED_WITH]->(asuka),
(asuka)<-[:CONNECTED_WITH]-(kjg),
(michael)-[:CONNECTED_WITH]->(steve),
(steve)<-[:CONNECTED_WITH]-(michael),
(asuka)-[:CONNECTED_WITH]->(john),
(john)<-[:CONNECTED_WITH]-(asuka),
(asuka)-[:CONNECTED_WITH]->(steve),
(steve)<-[:CONNECTED_WITH]-(asuka),
(kjg)-[:CONNECTED_WITH]->(michael),
(michael)<-[:CONNECTED_WITH]-(kjg)

Domain model

MATCH (a)-[r]->(b) WHERE labels(a) <> [] AND labels(b) <> []
RETURN DISTINCT head(labels(a)) AS This, type(r) as To, head(labels(b)) AS That

Match

We would like to see what required and optional skills people are missing. The less they are missing, the more possible it is they are good candidates for further screening of the job.

Missing required skills

MATCH (p:Person)
MATCH (:Job {title:'Information Developer'})-[:REQUIRED_SKILL]->(req_skill:Skill)
WHERE NOT (p)-[:KNOWS]->(req_skill)
WITH p.name as Person, count(req_skill.name) as Number_of_required_skills_missing, collect(req_skill.name) as Missing_required_skills
RETURN Person, Missing_required_skills
ORDER BY Number_of_required_skills_missing;

Missing optional skills

MATCH (p:Person)
MATCH (:Job {title:'Information Developer'})-[:OPTIONAL_SKILL]->(opt_skill:Skill)
WHERE NOT (p)-[:KNOWS]->(opt_skill)
WITH p.name as Person, count(opt_skill.name) as Number_of_optional_skills_missing, collect(opt_skill.name) as Missing_optional_skills
RETURN Person, Missing_optional_skills
ORDER BY Number_of_optional_skills_missing;

Location of person

MATCH (:Job {title:'Information Developer'})-[:DESIRED_LOCATION]->(desired_city:City)
WITH collect(desired_city) as desired_cities
MATCH (p:Person)-[:LIVES_IN]->(city)
RETURN p.name as Person, city.name as Lives_in,
CASE WHEN city IN desired_cities THEN "Lives in the desired city" ELSE "Does not live in the desired city" END AS Match_with_desired_city;

Conclusions

We can see that Karl-Johan and Michael are our top two candidates for matching the skills of the job as Information Developer, because they have the closest matching skill set for the position. Karl-Johan is based in Lund, while Michael is based in Boston, so Karl-Johan would be a better candidate since Lund is closer to Malmo than Boston is to London, and Karl-Johan is therefore also assumed to already have work permit.

The result could aid in follow up interviews, to get hints how the candidate is aiming to learn missing skills.

A graph database is an intuitive and easy tool for managing a network of professional candidates, and for matching candidates with jobs. It can be used for initial screening of candidates based on desired skills. Data could be harvested from connections in professional networks such as LinkedIn.

Equally important as having the right skill set, is having the appropriate experience, right attitude, right motivation, and having a career goal which the hiring manager will be able to support. Further screening of the candidate is therefore required before making a hiring decision.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment