2
votes

I am not sure how to phrase this question as I don't even know what it's called but I will try.

You can imagine that I have the following graph representation and relationships in my neo4j instance:

enter image description here

The question I want to ask Neo4j is the below: What are the movies that only Agency-A actors acted?

This is a simple sample though. In my case, I have thousands of actors who joined an agent and thousands of movies that an actor potentially acted.

PS: I would also appreciate if you can tell me the name of the thing I am trying to do :)

Update

I was able to have something solid working. Here is the data set:

CREATE (AgencyA:Agency {name: 'Agency-A'})
CREATE (Actor1:Person {name: 'Actor-1'})
CREATE (Actor2:Person {name: 'Actor-2'})
CREATE (Actor3:Person {name: 'Actor-3'})
CREATE (Actor4:Person {name: 'Actor-4'})
CREATE (Actor5:Person {name: 'Actor-5'})
CREATE 
  (AgencyA)-[:ACQUIRED]->(Actor1), 
  (AgencyA)-[:ACQUIRED]->(Actor3), 
  (AgencyA)-[:ACQUIRED]->(Actor5)

CREATE (MovieA:Movie {name: "Movie-A"})
CREATE (MovieB:Movie {name: "Movie-B"})
CREATE (MovieC:Movie {name: "Movie-C"})

CREATE 
  (MovieA)-[:EMPLOYED]->(Actor1),
  (MovieA)-[:EMPLOYED]->(Actor5),
  (MovieB)-[:EMPLOYED]->(Actor1),
  (MovieB)-[:EMPLOYED]->(Actor3),
  (MovieB)-[:EMPLOYED]->(Actor5),
  (MovieC)-[:EMPLOYED]->(Actor2),
  (MovieC)-[:EMPLOYED]->(Actor5)

Here is the query:

MATCH (agency:Agency {name:"Agency-A"})-[:ACQUIRED]->(actor:Person)<-[:EMPLOYED]-(movie:Movie)
RETURN distinct movie.name

The result:

Movie-C

Movie-B

Movie-A

which is not what I want to get out. What I am interested in is the movie where only Agency-A actors have been employed, not any other actor. So, the result should be:

Movie-A

Movie-B

1

1 Answers

3
votes

In Cypher this is dead easy :)

MATCH (agency:Agency {name:"AgencyA"})<-[:JOINED]-(actor:Actor)-[:ACTED_IN]->(movie:Movie)
RETURN distinct movie.name

If an Actor might have joined the same agency multiple times (thus have more than one JOINED relationship to the same agency), you would distinct them before connecting the movies :

MATCH (agency:Agency {name:"AgencyA"})<-[:JOINED]-(actor:Actor)
WITH distinct actor as actor
MATCH (actor)-[:ACTED]->(movie:Movie)
RETURN distinct movie.name

UPDATE

After the clarification that no other persons could have played in a Movie where Agency-A people have been employed, this is a working query :

MATCH (agency:Agency { name:"Agency-A" })-[:ACQUIRED]->(actor:Person)<-[:EMPLOYED]-(movie:Movie)
WITH DISTINCT movie, collect(actor) AS actors
MATCH (movie)-[:EMPLOYED]->(allemployees:Person)
WITH movie, actors, count(allemployees) AS c
WHERE c = size(actors)
RETURN movie.name

Here, we are comparing the total number of the movie employees to the size of employees firstly matched by the Agency-A

You can test it here :

http://console.neo4j.org/r/s9t6en