Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save jexp/b0d21122a6f1a5d7cbc7 to your computer and use it in GitHub Desktop.
Save jexp/b0d21122a6f1a5d7cbc7 to your computer and use it in GitHub Desktop.
Neo4j cypher for co-favorited plus additional attribute

Neo4j cypher for co-favorited plus additional attribute

Answering an Stackoverflow Question.

I am learning Neo4j and decided to take one of the sample queries and add a twist to it. I took this example http://docs.neo4j.org/chunked/stable/cypher-cookbook-co-favorited-places.html and wanted to say what if there was an additional attribute that you could use to filter the results by. My test I put together was to have tags in the graph as well and then I wanted to search by overlapped favorites desc then by overlapping tags desc.

Here is the sample data I am using:

CREATE (Keanu:Person {name:'Keanu Reeves', born:1964})
CREATE (Carrie:Person {name:'Carrie-Anne Moss', born:1967})
CREATE (Laurence:Person {name:'Laurence Fishburne', born:1961})
CREATE (Hugo:Person {name:'Hugo Weaving', born:1960})
CREATE (UserBart:User {username:'bart' })
CREATE (UserHomer:User {username:'homer' })
CREATE (UserMarge:User {username:'marge' })
CREATE (Male:Tag {name:'male' })
CREATE (Female:Tag {name:'female' })
CREATE (BadHair:Tag {name:'badhair' })
CREATE
  (UserBart)-[:FAVORITE]->(Keanu),
  (UserBart)-[:FAVORITE]->(Laurence),
  (UserBart)-[:FAVORITE]->(Carrie),
  (UserHomer)-[:FAVORITE]->(Carrie),
  (UserHomer)-[:FAVORITE]->(Hugo),
  (UserMarge)-[:FAVORITE]->(Keanu),
  (UserMarge)-[:FAVORITE]->(Laurence),
  (UserMarge)-[:FAVORITE]->(Carrie),
  (Male)-[:TAGGED]->(Keanu),
  (Male)-[:TAGGED]->(Laurence),
  (Male)-[:TAGGED]->(Hugo),
  (Female)-[:TAGGED]->(Carrie),
  (BadHair)-[:TAGGED]->(Keanu),
  (BadHair)-[:TAGGED]->(Laurence)

I would like to answer this question: for all the people who favorited Keanu Reeves, who else have they favorited and if there is a tie breaker show the person with the most related tags first. With the sample data, there are two people that were favorited by users who also favorited Keanu: Carrie and Laurence. Carrie has no overlapping tags with Keanu while Laurence has two overlapping tags. I would like to get the following results:

Name        SharedFavCount     OverlapTagCount
Laurence    2                  2
Carrie      2                  0

I have tried a bunch of different cyphers with different combination and haven’t been able to crack it.

The cypher I find the oddest - I probably don’t fully understand cyphers yet - is this one where I am explicitly saying I don’t want Keanu in the results but alas he appears in the results. Here is that cypher along with the results.

MATCH (anchor:Person)<-[:FAVORITE]-(u:User)-[:FAVORITE]->(similiar:Person)
OPTIONAL MATCH (anchor)<-[:TAGGED]-(t:Tag)-[:TAGGED]->(similiar2:Person)
WHERE anchor.name = 'Keanu Reeves'
AND similiar.name <> 'Keanu Reeves'
AND similiar.name = similiar2.name
return similiar.name, count(DISTINCT u.username), count(DISTINCT t.name)

and the results for that cypher:

Name             SharedFavCount      OverlapTagCount
Carrie           3                   0
Hugo             1                   0
Laurence         2                   2
Keanu            2                   0

Any ideas how I can get the desired results?

Answer

Your WHERE filtering for "Keanu Reeves" is applied to the wrong match, move it upwards behind the MATCH clause. And add an ORDER BY for your tie-break rule.

You can also simplify your query, you don’t need the additional constraints, rather reuse the similiar identifier. Keanu Reeves cannot appear as similiar as the FAVORITE relationship pointing to him is already used in the path.

MATCH (anchor:Person)<-[:FAVORITE]-(u:User)-[:FAVORITE]->(similiar:Person)
WHERE anchor.name = 'Keanu Reeves'
OPTIONAL
MATCH (anchor)<-[:TAGGED]-(t:Tag)-[:TAGGED]->(similiar)
RETURN similiar.name, count(DISTINCT u.username) as favs, count(DISTINCT t.name) as tags
ORDER BY favs DESC, tags DESC

Returning the same results:

But it’s not what you want.

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