Srdjan Marjanovic
Srdjan Marjanovic

Reputation: 372

Match nodes with and without a relationship in Neo4j

I am using the sample movie graph which comes with a Neo4j installation.

I would like to get an actor (by name), roles which he acted in movies and all other movies (which he isn't yet connected to).

The closest I can get is something like the following, but the actor, roles and actedInMovies repeat as many times as there are otherMovies.

MATCH (actor{name:'Bill Paxton'})-[roles:ACTED_IN]->(actedInMovies), (otherMovies:Movie)
WHERE NOT (actor)-[:ACTED_IN]->(otherMovies)
RETURN actor, roles, actedInMovies, otherMovies

How can I get only one result for the actor, roles for corresponding movie, and all other movies?

Thanks in advance!

Upvotes: 1

Views: 152

Answers (1)

Dave Bennett
Dave Bennett

Reputation: 11216

how about a slightly different approach First get all of the movies that Bill Paxton acted in and then with that collection of movies find all of the movies that aren't in it. Then return Bill Paxton, the collection of movies he acted in and the collection of movies he did not act in (i.e. the remainder)

MATCH (actor:Person {name:'Bill Paxton'})-[r:ACTED_IN]->(acted:Movie) 
with actor, collect(acted) as acted_in_movies, collect(r) as roles
MATCH (other:Movie)
WHERE none (acted in acted_in_movies where acted = other) 
RETURN actor.name, acted_in_movies, roles, collect(other) as other_movies

Updated query to reflect the data set I tested it with. Added the collection of role names and change the movie nodes to titles for the result set.

MATCH (actor {name:'Bill Paxton'})-[r:ACTS_IN]->(acted) 
with actor, collect(acted) as acted_in_movies, collect(acted.title) as acted_titles, collect(r.name) as roles
MATCH (other:Movie)
WHERE none (acted in acted_in_movies where acted = other) 
RETURN actor.name, acted_titles, roles, collect(other.title) as other_movies

Upvotes: 1

Related Questions