Jaap
Jaap

Reputation: 89

Problems with simple Cypher Query: complicated match statement

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

Answers (2)

Rajendra Kadam
Rajendra Kadam

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

InverseFalcon
InverseFalcon

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

Related Questions