I wanted to find out which all person nodes are associated to a given Movie and in what roles. Consider that my Movie database has several relations -
Person acted in a movie
Person directed a movie
Person reviewed a movie
Person followed a movie ......... and many more.
In a relational database this would probably be setup as separate tables - ACTED table, DIRECTED table etc each of which would map the Person's primary key and the movies key. In Neo4j relations played the role. But If I wanted to find out all of theses above results would I have to fire a separate query for each type of relation ?
Something like
Fortunately CYPHER provides a very useful type keyword. The same result can be obtained with a single query as seen below:
Cypher agains come to our rescue with the labels keyword:
Person acted in a movie
Person directed a movie
Person reviewed a movie
Person followed a movie ......... and many more.
In a relational database this would probably be setup as separate tables - ACTED table, DIRECTED table etc each of which would map the Person's primary key and the movies key. In Neo4j relations played the role. But If I wanted to find out all of theses above results would I have to fire a separate query for each type of relation ?
Something like
MATCH (a:Person)-[:ACTED_IN]->(m:Movie) WHERE m.title='Cloud Atlas' RETURN aThis would mean firing n cypher queries and processing each result separately. This would be a very inefficient way to do it. Also as the number of possible relations grow, change the code would have to be updated.
MATCH (a:Person)-[:DIRECTED]->(m:Movie) WHERE m.title='Cloud Atlas' RETURN a
MATCH (a:Person)-[:REVIEWED]->(m:Movie) WHERE m.title='Cloud Atlas' RETURN a
Fortunately CYPHER provides a very useful type keyword. The same result can be obtained with a single query as seen below:
public Map<String, String> getAssociationsToMovie(String movieName, int released) {I tested the same as below:
try (Transaction tx = graphDb.beginTx()) {
Map<String, Object> params = new HashMap<>();
params.put("mName", movieName);
params.put("releasedYear", released);
Result result = graphDb.execute(
"MATCH (p:Person)-[r]->(m:Movie) WHERE m.title='Cloud Atlas' RETURN p.name AS pName, type(r) as assocn",
params);
if (!result.hasNext()) {
returnnull;
}
Map<String, String> soln = new HashMap<>();
while (result.hasNext()) {
Map<String, Object> row = result.next();
String pName = (String) row.get("pName");
String assocn = (String) row.get("assocn");
soln.put(pName, assocn);// assuming person has only one relationship to
// a given Movie
}
return soln;
}
}
publicstatic void main(String[] args) {The output of the above code is:
MovieDAO movieDAO = new MovieDAO();
Map<String, String> result = movieDAO.getAssociationsToMovie("Cloud Atlas", 2012);
result.keySet().forEach(key -> System.out.println(key + " - " + result.get(key) ));
}
Lana Wachowski - DIRECTEDSimilarly consider the case that we have various type of Nodes all asociated with a movie. And we would like to fetch them all in a single query. How do we identify the label of the node ?
Tom Hanks - ACTED_IN
Tom Tykwer - DIRECTED
Hugo Weaving - ACTED_IN
Halle Berry - ACTED_IN
Stefan Arndt - PRODUCED
Jim Broadbent - ACTED_IN
Jessica Thompson - REVIEWED
Andy Wachowski - DIRECTED
David Mitchell - WROTE
Cypher agains come to our rescue with the labels keyword:
MATCH (a)-[r]->(m:Movie)The output of the code gives the values as seen here
WHERE m.title='Cloud Atlas'
RETURN labels(a) as NodeType, a