Reputation: 89
I'm new to Neo4J and Cypher and decided to play around with the Movie sample data that is provided when installing Neo4J desktop.
I want to run a very simple query, namely to retrieve the titles of the movies which involved 3 people, Liv Tyler, Charlize Theron, and Bonnie Hunt. Matching up two people is not a problem (see the code below) but including a third one is difficult.
In SQL this wouldn't be a problem for me, but Cypher causes serious headaches. Here is the query so far:
MATCH (Person {name: "Liv Tyler"})-[:ACTED_IN]->(movie:Movie)<-[:DIRECTED]-(Person {name: "Bonnie Hunt"})
RETURN movie.title AS Title
I've tried to use AND
statements, but nothing works.
So how to include Charlize Theron in this query?
Upvotes: 1
Views: 106
Reputation: 4052
You can use multiple patterns to match three or more connections to a single node.
You can use the variable movie
which you are using in your query to refer same Movie
node to include the pattern (:Person {name: "Charlize Thero"})-[:ACTED_IN]->(movie)
.
MATCH (:Person {name: "Liv Tyler"})-[:ACTED_IN]->(movie:Movie)<-[:DIRECTED]-(:Person {name: "Bonnie Hunt"}),
(:Person {name: "Charlize Theron"})-[:ACTED_IN]->(movie)
RETURN movie.title AS Title
You can also rewrite the above query as follows:
MATCH (:Person {name: "Liv Tyler"})-[:ACTED_IN]->(movie:Movie),
(:Person {name: "Bonnie Hunt"})-[:DIRECTED]->(movie),
(:Person {name: "Charlize Theron"})-[:ACTED_IN]->(movie)
RETURN movie.title AS Title
Upvotes: 1
Reputation: 30397
If you have some arbitrary number of actors (parameterized), where you can't hardcode the :Person nodes in question, you can instead match on :Person nodes with their name in the parameter list, then filter based on the count of patterns found (you want to make sure all of the persons who acted in the movie are counted).
But if we do that first for directors, then we have some movie matches already, and can apply an all()
predicate on the list of actors to ensure they all acted in the movie.
Assuming two list parameters, one for actors, one for directors:
MATCH (director:Person)-[:DIRECTED]->(m:Movie)
WHERE director.name in $directors
WITH m, count(director) as directorCount
WHERE directorCount = size($directors)
AND all(actor IN $actors WHERE (:Person {name:actor})-[:ACTED_IN]->(m))
RETURN m.title as Title
Upvotes: 0