Skip to content

Latest commit

 

History

History
executable file
·
332 lines (249 loc) · 21.1 KB

socialNetworks.adoc

File metadata and controls

executable file
·
332 lines (249 loc) · 21.1 KB

Using a Professional Social Network to Target Potential Hires

Using a Professional Social Network to Target Potential Hires

This GraphGist

This GraphGist explores targeted 'marketing' on job networking sites such as LinkedIn, Viadeo, and Xing using a combination of techniques. Our toy professional networking site allows users and companies to use the site for free, but does charge for job posting, and offers several options on how to put the job posting in front of the most relevant (and hopefully qualified and interested) users.

Job Networking Platforms, an Introduction

For the majority of users, social networks—​including professional networking sites—​are free services used to connect with personal or professional contacts, join interest-specific groups, and network with potential employers, clients, or employees. To both make and sustain the magic of social networks and web 2.0, social network owners have to not only provide their users and potential customers with fast, powerful analytics, but also be able to sustain themselves while providing value to their shareholders.

This GraphGist explores how a social network provider, may use a graph database to both provide its customers and users with value while monetizing their service. In particular, it explores how a professional social network owner might provide high-value recommendations for groups in which to place job adverts.

The companies operating the social networks use various means to monetize their service, including sidebar ads from users and third parties, premium accounts, and more directed ads targeting particular users.

Companies and individuals purchasing services like advertisements from social network sites want the best bang for their buck: they are paying a premium to present their ad to potential clients, and they would rather not 'waste' views on users that have no interest in the product in question. Social networking services use a variety of means to offer their customers the best access to high-value targets. For example, social networks offer targeted ads based on combinations of:

User Interests

For example, if someone searches for 'butterflies' on Amazon.com while logged into Facebook, she is then presented with Lepidoptera-related ads across Facebook

Social Network

For example, companies using Facebook can target ads at the friends of particular users, as these users presumably share relevant characteristics with the initial users, such as location and interests

A brief description of our professional network:

Our network includes:

  • Persons: Persons, or the free users of the site, can be actively looking for work, happily employed and using the site to connect with fellow professionals, or a combination. Persons can make connections between themselves and other Persons, the Company they work for, Groups they belong to, Jobs they can express interest in, and Skills they are interested in or currently use.

  • Companies: Companies in this example are interested in hiring the best talent, and are willing to pay to present job postings (Jobs) to targeted potential employees.

  • Jobs: Jobs are posted by Companies and are associated with Skills

  • Skills: Associated with Persons and Jobs, Skills are used by Companies to find relevant potential employees and by Persons to find relevant Jobs and Groups.

  • Groups: Although Persons can form social connections with other Persons, Persons can also join Groups based on common interests, which may or may not include Skills, previous employers, educational experiences, or other shared characteristics.

Some loose ends:

This network assumes the following abstractions:

  • There’s no time but the present. The network ignores past Person-Job relationships and assumes all job postings, group membership, and social connections are current

  • Aside from id and a name, nodes don’t have other traits, emphasizing the power of the connections and relationships

Targeted Employment Ads: A Closer Look

From the point of view of the Companies participating in the Jobs posting market, paying for job ads is costly and often inefficient. Not only does the posting cost money, the Company has to process and filter applicants, a cost raised by ineffective targeting. In order to become more efficient, Companies are willing to pay a premium for higher precision.

Our toy network wants to offer Companies the two options for targeted advertisement: recommended Groups and recommended Experts.

If a Company chooses the first option, the company will be presented with recommended groups in which to advertise based the company’s needs.

If a Company chooses the second option, it will be presented with a list of high-value Persons the company may choose to target individually.

Let’s create the social network. The next sections will take a closer look at its characteristics and how it might use Neo4j to offer various solutions to clients.

//create the Person nodes
CREATE (`1`:Person {id:1, name:'Abeer Fathy'}), (`2`:Person {id:2, name:'An Yu-bao'}), (`3`:Person {id:3, name:'Anastasiya Vasilyev'}), (`4`:Person {id:4, name:'Anna Zaytesev'}), (`5`:Person {id:5, name:'Asley Leger'}),
(`6`:Person {id:6, name:'Aziza Hsuang-tsung'}), (`7`:Person {id:7, name:'Bai Vasilyev'}), (`8`:Person {id:8, name:'Barbra Schon'}), (`9`:Person {id:9, name:'Bart Kosana'}), (`10`:Person {id:10, name:'Bill Hinzman'}),
(`11`:Person {id:11, name:'Bill Cardille'}), (`12`:Person {id:12, name:'Bobba Fett'}), (`13`:Person {id:13, name:'Cai Shen'}), (`14`:Person {id:14, name:'Cammy Schott'}), (`15`:Person {id:15, name:'Cammy Vinogradov'}), (`16`:Person {id:16, name:'Cammy Sokolov'}), (`17`:Person {id:17, name:'Chan Morozov'}), (`18`:Person {id:18, name:'Chan Bang'}), (`19`:Person {id:19, name:'Charles Craig'}), (`20`:Person {id:20, name:'Chew Kwan-yew'}),
(`21`:Person {id:21, name:'Chiang Popov'}), (`22`:Person {id:22, name:'Chiu Xiao-yong'}), (`23`:Person {id:23, name:'Dai Lu-fang'}), (`24`:Person {id:24, name:'Dariya Solovynov'}), (`25`:Person {id:25, name:'Dariya Semyonov'}), (`26`:Person {id:26, name:'Dariya Vorobyrov'}), (`27`:Person {id:27, name:'David Cardille'}), (`28`:Person {id:28, name:'Deeanna Lacroix'}), (`29`:Person {id:29, name:'Deng Szeto'}), (`30`:Person {id:30, name:'Dina Schott'}),(`31`:Person {id:31, name:'David Schott'}),(`32`:Person {id:32, name:'Mary Schott'})

//create the Company nodes
CREATE (`company1`:Company {id:1, name:'CRC Press'}), (`company2`:Company {id:2, name:'Quantum Stabilzers'}), (`company3`:Company {id:3, name:'The SilverLogic'})

//create the Job nodes
CREATE (`job1`:Job {id:1, name:'Designer'}), (`job2`:Job {id:2, name:'Naval Eng.'}), (`job3`:Job {id:3, name:'Python Dev'})

//create the Skill nodes for the Python Developer Job
CREATE (`skill1`:Skill {id:1, name:'Django'}), (`skill2`:Skill {id:2, name:'Flask'}), (`skill3`:Skill {id:3, name:'Git'})

//create the Skill nodes for the Naval Engineer Job
CREATE (`skill4`:Skill {id:4, name:'CAD'}), (`skill5`:Skill {id:5, name:'Excel'}), (`skill6`:Skill {id:6, name:'Project Management'})

//create the Skill nodes for the Graphic Designer Job
CREATE (`skill7`:Skill {id:7, name:'Illustrator'}),(`skill8`:Skill {id:8, name:'InDesign'}), (`skill9`:Skill {id:9, name:'Photoshop'})

//create Job-Skill relationships
CREATE (`job1`)-[:HAS_SKILL]->(`skill7`), (`job1`)-[:HAS_SKILL]->(`skill8`),(`job1`)-[:HAS_SKILL]->(`skill9`),
	(`job2`)-[:HAS_SKILL]->(`skill4`), (`job2`)-[:HAS_SKILL]->(`skill5`),(`job2`)-[:HAS_SKILL]->(`skill6`),
	(`job3`)-[:HAS_SKILL]->(`skill1`),(`job3`)-[:HAS_SKILL]->(`skill2`)

//create the job-company relationshp
CREATE (`job1`)-[:JOB_AT]->(`company3`), (`job2`)-[:JOB_AT]->(`company2`), (`job3`)-[:JOB_AT]->(`company3`)

//create the Group nodes
CREATE (`group1`:Group {id:1, name:'Python Lovers'}), (`group2`:Group {id:2, name:'MIA Alums'}), (`group3`:Group {id:3, name:'Snakes Forever'})

CREATE (`group4`:Group {id:4, name:'Yachties Unite'}), (`group5`:Group {id:5, name:'Excel Support Group'}), (`group6`:Group {id:6, name:'Fishing is Life'})

CREATE(`group7`:Group {id:7, name:'Marketing Pros'}),(`group8`:Group {id:8, name:'Python Users Unite'}),(`group9`:Group {id:9, name:'Learn Python the Hard Way'})

//create the Person-Person relationships
CREATE (`1`)-[:KNOWS]->(`2`), (`1`)-[:KNOWS]->(`3`), (`1`)-[:KNOWS]->(`4`), (`1`)-[:KNOWS]->(`5`),
	(`2`)-[:KNOWS]->(`3`), (`2`)-[:KNOWS]->(`4`), (`2`)-[:KNOWS]->(`5`),
	(`3`)-[:KNOWS]->(`4`), (`3`)-[:KNOWS]->(`5`),
	(`4`)-[:KNOWS]->(`5`),
	(`5`)-[:KNOWS]->(`7`),
	(`6`)-[:KNOWS]->(`7`),
	(`8`)-[:KNOWS]->(`7`),
	(`9`)-[:KNOWS]->(`3`), (`9`)-[:KNOWS]->(`5`),
	(`10`)-[:KNOWS]->(`2`), (`10`)-[:KNOWS]->(`4`), (`10`)-[:KNOWS]->(`6`),
	(`11`)-[:KNOWS]->(`27`), (`11`)-[:KNOWS]->(`1`), (`11`)-[:KNOWS]->(`3`), (`11`)-[:KNOWS]->(`5`),
	(`12`)-[:KNOWS]->(`4`), (`12`)-[:KNOWS]->(`6`),
	(`13`)-[:KNOWS]->(`13`), (`13`)-[:KNOWS]->(`1`),
	(`14`)-[:KNOWS]->(`30`), (`14`)-[:KNOWS]->(`4`),
	(`15`)-[:KNOWS]->(`30`), (`15`)-[:KNOWS]->(`26`), (`15`)-[:KNOWS]->(`21`), (`15`)-[:KNOWS]->(`3`), (`15`)-[:KNOWS]->(`5`),
	(`16`)-[:KNOWS]->(`11`), (`16`)-[:KNOWS]->(`4`),
	(`17`)-[:KNOWS]->(`17`), (`17`)-[:KNOWS]->(`28`),
	(`18`)-[:KNOWS]->(`12`), (`18`)-[:KNOWS]->(`2`),
	(`19`)-[:KNOWS]->(`3`), (`19`)-[:KNOWS]->(`5`),
	(`20`)-[:KNOWS]->(`1`), (`20`)-[:KNOWS]->(`2`),
	(`21`)-[:KNOWS]->(`1`), (`21`)-[:KNOWS]->(`3`), (`21`)-[:KNOWS]->(`5`),
	(`22`)-[:KNOWS]->(`4`), (`22`)-[:KNOWS]->(`6`), (`22`)-[:KNOWS]->(`2`),
	(`24`)-[:KNOWS]->(`7`), (`24`)-[:KNOWS]->(`4`),
	(`25`)-[:KNOWS]->(`3`), (`25`)-[:KNOWS]->(`5`),
	(`26`)-[:KNOWS]->(`18`), (`26`)-[:KNOWS]->(`2`), (`26`)-[:KNOWS]->(`4`), (`26`)-[:KNOWS]->(`6`),
	(`27`)-[:KNOWS]->(`11`), (`27`)-[:KNOWS]->(`1`), (`27`)-[:KNOWS]->(`3`), (`27`)-[:KNOWS]->(`5`),
	(`28`)-[:KNOWS]->(`4`),
	(`29`)-[:KNOWS]->(`19`), (`29`)-[:KNOWS]->(`1`),
	(`30`)-[:KNOWS]->(`14`),
	(`31`)-[:KNOWS]->(`32`)

//Create the Person-Group relationships

//Groups of interest to Graphic Designers
CREATE (`1`)-[:MEMBER]->(`group1`), (`30`)-[:MEMBER]->(`group2`),(`2`)-[:MEMBER]->(`group1`), (`3`)-[:MEMBER]->(`group1`), (`4`)-[:MEMBER]->(`group1`)
CREATE (`5`)-[:MEMBER]->(`group2`), (`6`)-[:MEMBER]->(`group2`), (`7`)-[:MEMBER]->(`group2`), (`8`)-[:MEMBER]->(`group2`), (`9`)-[:MEMBER]->(`group2`)
CREATE (`1`)-[:MEMBER]->(`group3`), (`3`)-[:MEMBER]->(`group3`), (`5`)-[:MEMBER]->(`group3`), (`7`)-[:MEMBER]->(`group3`), (`9`)-[:MEMBER]->(`group3`)

//Groups of interest to Naval Engineers
CREATE (`11`)-[:MEMBER]->(`group4`), (`12`)-[:MEMBER]->(`group4`), (`13`)-[:MEMBER]->(`group4`), (`14`)-[:MEMBER]->(`group4`)
CREATE (`15`)-[:MEMBER]->(`group4`), (`16`)-[:MEMBER]->(`group4`), (`17`)-[:MEMBER]->(`group4`), (`18`)-[:MEMBER]->(`group5`), (`19`)-[:MEMBER]->(`group5`)
CREATE (`11`)-[:MEMBER]->(`group5`), (`13`)-[:MEMBER]->(`group5`), (`15`)-[:MEMBER]->(`group5`), (`17`)-[:MEMBER]->(`group5`), (`19`)-[:MEMBER]->(`group5`)

//Groups of interest to Python Engineers
CREATE (`21`)-[:MEMBER]->(`group6`), (`22`)-[:MEMBER]->(`group6`), (`23`)-[:MEMBER]->(`group6`), (`24`)-[:MEMBER]->(`group6`)
CREATE (`25`)-[:MEMBER]->(`group7`), (`26`)-[:MEMBER]->(`group7`)
CREATE (`21`)-[:MEMBER]->(`group9`), (`23`)-[:MEMBER]->(`group9`), (`25`)-[:MEMBER]->(`group9`), (`27`)-[:MEMBER]->(`group5`), (`29`)-[:MEMBER]->(`group5`),(`32`)-[:MEMBER]->(`group3`)

//create the Person-Skill relationships
CREATE (`1`)-[:HAS_SKILL]->(`skill1`), (`1`)-[:HAS_SKILL]->(`skill2`), (`1`)-[:HAS_SKILL]->(`skill3`), (`1`)-[:HAS_SKILL]->(`skill4`),
	(`2`)-[:HAS_SKILL]->(`skill1`), (`2`)-[:HAS_SKILL]->(`skill2`), (`2`)-[:HAS_SKILL]->(`skill3`),
	(`3`)-[:HAS_SKILL]->(`skill1`), (`3`)-[:HAS_SKILL]->(`skill2`),
	(`4`)-[:HAS_SKILL]->(`skill1`),
	(`5`)-[:HAS_SKILL]->(`skill1`),
	(`6`)-[:HAS_SKILL]->(`skill1`),
	(`8`)-[:HAS_SKILL]->(`skill1`),
	(`9`)-[:HAS_SKILL]->(`skill1`), (`9`)-[:HAS_SKILL]->(`skill2`),
	(`10`)-[:HAS_SKILL]->(`skill1`), (`10`)-[:HAS_SKILL]->(`skill2`), (`10`)-[:HAS_SKILL]->(`skill3`),
	(`11`)-[:HAS_SKILL]->(`skill4`), (`11`)-[:HAS_SKILL]->(`skill5`), (`11`)-[:HAS_SKILL]->(`skill6`), (`11`)-[:HAS_SKILL]->(`skill7`),
	(`12`)-[:HAS_SKILL]->(`skill4`), (`12`)-[:HAS_SKILL]->(`skill5`),
	(`13`)-[:HAS_SKILL]->(`skill4`), (`13`)-[:HAS_SKILL]->(`skill5`),
	(`14`)-[:HAS_SKILL]->(`skill4`), (`14`)-[:HAS_SKILL]->(`skill5`),
	(`15`)-[:HAS_SKILL]->(`skill4`), (`15`)-[:HAS_SKILL]->(`skill5`), (`15`)-[:HAS_SKILL]->(`skill6`), (`15`)-[:HAS_SKILL]->(`skill7`), (`15`)-[:HAS_SKILL]->(`skill8`),
	(`16`)-[:HAS_SKILL]->(`skill4`), (`16`)-[:HAS_SKILL]->(`skill5`),
	(`17`)-[:HAS_SKILL]->(`skill4`), (`17`)-[:HAS_SKILL]->(`skill5`),
	(`18`)-[:HAS_SKILL]->(`skill4`), (`18`)-[:HAS_SKILL]->(`skill5`),
	(`19`)-[:HAS_SKILL]->(`skill4`), (`19`)-[:HAS_SKILL]->(`skill5`),
	(`20`)-[:HAS_SKILL]->(`skill7`), (`20`)-[:HAS_SKILL]->(`skill8`),
	(`21`)-[:HAS_SKILL]->(`skill7`), (`21`)-[:HAS_SKILL]->(`skill8`), (`21`)-[:HAS_SKILL]->(`skill9`),
	(`22`)-[:HAS_SKILL]->(`skill7`), (`22`)-[:HAS_SKILL]->(`skill8`), (`22`)-[:HAS_SKILL]->(`skill9`),
	(`24`)-[:HAS_SKILL]->(`skill7`), (`24`)-[:HAS_SKILL]->(`skill8`),
	(`25`)-[:HAS_SKILL]->(`skill7`), (`25`)-[:HAS_SKILL]->(`skill8`),
	(`26`)-[:HAS_SKILL]->(`skill7`), (`26`)-[:HAS_SKILL]->(`skill8`), (`26`)-[:HAS_SKILL]->(`skill9`),
	(`27`)-[:HAS_SKILL]->(`skill7`), (`27`)-[:HAS_SKILL]->(`skill8`), (`27`)-[:HAS_SKILL]->(`skill9`),
	(`28`)-[:HAS_SKILL]->(`skill4`),
	(`29`)-[:HAS_SKILL]->(`skill7`), (`29`)-[:HAS_SKILL]->(`skill8`),
	(`30`)-[:HAS_SKILL]->(`skill7`),
	(`31`)-[:HAS_SKILL]->(`skill1`)

//create the user-company relationships
CREATE (`1`)-[:WORKS_AT]->(`company1`), (`2`)-[:WORKS_AT]->(`company2`), (`3`)-[:WORKS_AT]->(`company3`),
(`4`)-[:WORKS_AT]->(`company1`), (`5`)-[:WORKS_AT]->(`company2`), (`6`)-[:WORKS_AT]->(`company3`), (`7`)-[:WORKS_AT]->(`company1`), (`8`)-[:WORKS_AT]->(`company2`), (`9`)-[:WORKS_AT]->(`company3`), (`10`)-[:WORKS_AT]->(`company1`), (`11`)-[:WORKS_AT]->(`company2`), (`12`)-[:WORKS_AT]->(`company3`), (`13`)-[:WORKS_AT]->(`company1`), (`14`)-[:WORKS_AT]->(`company2`), (`15`)-[:WORKS_AT]->(`company3`), (`16`)-[:WORKS_AT]->(`company1`), (`17`)-[:WORKS_AT]->(`company2`), (`18`)-[:WORKS_AT]->(`company3`), (`19`)-[:WORKS_AT]->(`company1`), (`20`)-[:WORKS_AT]->(`company2`),(`30`)-[:WORKS_AT]->(`company3`)

RETURN *
LIMIT 50

A Closer Look at the Network

Groups, their Members, and their Skills

MATCH (s:Skill)<-[:HAS_SKILL]-(p:Person)-[:MEMBER]->(g:Group)
RETURN g.name AS Group, s.name AS Skill, count(DISTINCT p) AS `Members`
ORDER BY Skill ASC, Members DESC

If a company were interested in hiring Django developers, there are several groups competing for ad placement. If a Company has enough resources to advertise a Job to one group, which group should it advertise to?

Companies, their Employees, and their Skills

MATCH (c:Company)<-[:WORKS_AT]-(p:Person)-[:HAS_SKILL]->(s:Skill)
RETURN c.name AS Company, count(DISTINCT p) AS `Employees`, s.name AS `Has Skill`
ORDER BY Company DESC, Employees DESC

Assuming the Companies in our network are looking for employees with similar skillsets and social fit as their current employees, a Company might prefer a job candidate with more connections to current employees over one with more connections to experts in a particular Skill, depending on the position and how easy required Skills are to learn.

Companies, their Open Jobs, and their Skills

MATCH (c:Company)<-[:JOB_AT]-(j:Job)-[:HAS_SKILL]->(s:Skill)
RETURN c.name AS Company, j.name AS `Open Jobs`, collect(DISTINCT  s.name) AS `Skills Required`
ORDER BY Company ASC, `Open Jobs` DESC

Continuing the example from above, notice that the Company The SilverLogic has an open job for a Python Developer that requires the skills Django and Flask. Let’s see which group might be the best to advertise this open position.

Finding the Best Group in which to Advertise

Finding Target Groups through Employees

MATCH (p:Person)-[:WORKS_AT]->(c:Company), (p)-[:MEMBER]->(g:Group)
WHERE c.name = 'The SilverLogic'
RETURN DISTINCT c.name AS Company, g.name AS `Target Groups`, count(DISTINCT p) AS `Count of Member Employees`
ORDER BY Company DESC, `Count of Member Employees` DESC

If The SilverLogic were looking for a low-skill worker, like a high-school intern, a good strategy might be to simply look for groups with the highest number of current employees. It seems like a lot of The SilverLogic employees are the members of the group MIA Alums. That group seems like a good place to advertise for a Python Developer internship.

Finding Target Groups through Employees

with a Similar Skill Set as the Open Job

MATCH (c:Company)<-[:JOB_AT]-(j:Job)-[:HAS_SKILL]->(s:Skill),(s)<-[:HAS_SKILL]-(p:Person)-[:WORKS_AT]->(c),(p)-[:MEMBER]->(g:Group)
WHERE c.name = 'The SilverLogic'
AND j.name = 'Python Dev'
RETURN DISTINCT c.name AS Company, j.name AS Job, g.name AS Group, count(DISTINCT p) AS `Count of Member Employees`
ORDER BY  Company,`Count of Member Employees` DESC

Assuming The SilverLogic is looking for skilled workers that will work well with current employees, filtering for job-specific skills in addition to social connections may render useful results. In the case of The SilverLogic and its quest for a Python developer, there are several groups to choose from, two of which are better candidates for an ad than the last.

Targeting Experts

Taking a slightly different approach, the social network operators may want to offer companies the option to target ads at a particular number of experts in a particular skillset. This allows companies to advertise to qualified users without compromising the privacy of their targets or the quality of their results

Find an Expert

Let’s define an expert as someone with lots people in his or her network with the same skills. The assumption is that if an individual has a particular skill, and knows a lot of others with the same skill (met through conferences, work, clubs), he or she has a greater depth of knowledge than a skilled individual with few contacts with the same skill.

Let’s continue the search for a suitable Python developer. The following query returns a list of developers that both match the qualifications of the job in question and have connections that also match the job in question. Since the job has multiple skills attached to it, we’re going to use the collect() Cypher function.

MATCH (j:Job)-[:HAS_SKILL]->(s:Skill), (s)<-[:HAS_SKILL]-(expert:Person)-[:KNOWS]->(a:Person)-[:HAS_SKILL]->(s)
WHERE j.name = 'Python Dev'
RETURN DISTINCT expert.name AS Person, collect(DISTINCT s.name) AS Skill, count(a) AS `# Connections`
ORDER BY `# Connections` DESC

If a company is interested in a Python developer with Django and Flask as Skills, it can purchase an ad from the social network operator that offers ads to the top Python developers within some geographical or other constraints, and alert qualified users of the opportunity.

For more information on how to find experts in a network, take a look at 'Aardvark: The Anatomy of a Large-Scale Social Search Engine'

Conclusion

By harnessing the power of graph databases, social networks ranging from niche dating sites to networking giants such as LinkedIn have been able to increase their processing speed and quality of service. The examples above demonstrate how easy it is to find potential candidates—​for future employment or otherwise—​using a few simple queries.

Why Neo4j?

Neo4j Logo

Although Cypher has extraordinary features that might immediately improve recommendations, using these very simple and related searches can produce practical results across a variety of analytical needs.