Search This Blog

Monday, 27 March 2017

Neo4j - Traversing along the directions of a Relation

Neo4j Relationships are what connect any two nodes in the graph.  To copy paste from the Neo4j guide:
Relationships organize nodes into arbitrary structures, allowing a graph to resemble a list, a tree, a map, or a compound entity — any of which can be combined into yet more complex, richly inter-connected structures.

The cool thing about Relations is that it need not be directional. We can even traverse the relation in either direction. For instance consider the Person ACTED_IN Movie relation. Here I could run a query to get all Actors from an single movie as well all movies of a single actor:
public List<Actor> getActorsInMovie(String movieName, int released);
public List<Movie> getMoviesActedIn(String actorName);
Here is the code for the two:
public List<Actor> getActorsInMovie(String movieName, int released) {
    try (Transaction tx = graphDb.beginTx()) {
      Map<String, Object> params = new HashMap<>();
      params.put("mName", movieName);
      params.put("releasedYear", released);
      Result result = graphDb.execute(
          "MATCH (a:Person)-[:ACTED_IN]->(m:Movie) WHERE m.title={mName} and m.released={releasedYear} RETURN a",
          params);
      if (!result.hasNext()) {
        return null;
      }
      List<Actor> actors = new ArrayList<>();
      while (result.hasNext()) {
        actors.add(extractActor((Node) result.next().get("a")));
      }
      return actors;
    }
The query here is : MATCH (a:Person)-[:ACTED_IN]->(m:Movie) WHERE m.title={mName} and m.released={releasedYear} RETURN a and the output on calling this method:
Movie [ id : 154, title : Something's Gotta Give, released : 2003, tagline : null]
Movie [ id : 100, title : Johnny Mnemonic, released : 1995, tagline : The hottest data on earth. In the coolest head in town]
Movie [ id : 87, title : The Replacements, released : 2000, tagline : Pain heals, Chicks dig scars... Glory lasts forever]
Movie [ id : 3, title : The Devil's Advocate, released : 1997, tagline : Evil has its winning ways]
Movie [ id : 2, title : The Matrix Revolutions, released : 2003, tagline : Everything that has a beginning has an end]
Movie [ id : 1, title : The Matrix Reloaded, released : 2003, tagline : Free your mind]
Movie [ id : 0, title : The Matrix, released : 1999, tagline : Welcome to the Real World]
Similar is the method to retrieve actors with a slight difference in query:
MATCH (a:Person)-[:ACTED_IN]->(m:Movie) WHERE a.name={aName} RETURN m Here while the WHERE clause has changed the MATCH clause is the same and RETURN now fetches the movie nodes instead of actor nodes.
public List<Movie>getMoviesActedIn(String actorName) {
    try (Transaction tx = graphDb.beginTx()) {
      Map<String, Object> params = new HashMap<>();
      params.put("aName", actorName);
      Result result = graphDb.execute(
          "MATCH (a:Person)-[:ACTED_IN]->(m:Movie) WHERE a.name={aName} RETURN m",
          params);
      if (!result.hasNext()) {
        return null;
      }
      List<Movie> movies = new ArrayList<>();
      while (result.hasNext()) {
        movies.add(extractMovie((Node)result.next().get("m")));
        }
      return movies;
    }
The output is as below:
Actor [ title : Dina Meyer, yearBorn : 1968 ]
Actor [ title : Ice-T, yearBorn : 1958 ]
Actor [ title : Keanu Reeves, yearBorn : 1964 ]
Actor [ title : Takeshi Kitano, yearBorn : 1947 ]

No comments:

Post a Comment