Introduction - how to use neo4j in java

1. Introduction

In this post, I will build a small web application in java by learning how to connect to as well as manipulate on neo4j database. Neo4j offers a rich set of integration possibilities for developers using Java or other JVM-languages. Following the instruction on the website, we will build a small web app for the movie database.

2.Create a project And add neo4j driver dependencies

Here, I use IntelliJ IDEA as dev tool and Maven as project management tool. So, select maven-archetype-webapp.

Smiley face

After that, go to the maven repository website(Link) and add dirver dependency to pom.xml.

<dependency>
    <groupId>org.neo4j.app</groupId>
    <artifactId>neo4j-server</artifactId>
    <version>3.5.5</version>
</dependency>
<dependency>
      <groupId>org.neo4j.driver</groupId>
      <artifactId>neo4j-java-driver</artifactId>
      <version>1.7.2</version>
</dependency>

3. Play with the movie dataSet.

Using the data provided by the neo4j guides. Run all CQL commands and get the result.

Instruction from the guide

The Movie Graph is a mini graph application containing actors and directors that are related through the movies they've collaborated on.

This guide will show you how to:

Create: insert movie data into the graph
Find: retrieve individual movies and actors
Query: discover related actors and directors
Solve: the Bacon Path

After executing the CQL languages, what we will get the graph database

Smiley face

4. Establish Connection.

In order to use the diver, make connection to the neo4j database. we should do the following things.

  1. Provide a connection URL with username and password. The URL has the format: bolt://username:password@localhost

  2. Get a driver instance

  3. From the driver, create a session.

  4. invoke session.run() method by parsing two parameters. 1). Cypher Query Language with parameters 2). Parameters given in the type of java map, with key-value pairs.

  5. It will return result of Statement Result(see Documantation for detail ).It extends the Iterator class. so, it has hasNext() method and next() method to iterate through the result.

  6. Close and session and close the database.

Cypher Query Language with parameters :

For Query String reuse and injection prevention. we will passing the parameters by Parameter Binding. In their document, they say:

Cypher supports querying with parameters. This means developers don't have to resort to string building to create a query. Additionally, parameters make caching of execution plans much easier for Cypher, thus leading to faster query execution times.

Where to use.

Parameters can be used for:

literals and expressions
node and relationship ids
for explicit indexes only: index values and queries

Where cannot be used.

Parameters cannot be used for the following constructs, as these form part of the query structure that is compiled into a query plan:
property keys; so, MATCH (n) WHERE n.$param = 'something' is invalid
relationship types
labels

There are multiple excellent Examples to use CQL With parameters in neo4j documentation

Here, I wrote codes to test connection with Unit Test.

package com.neo4j.movies;

import org.junit.Test;
import org.neo4j.driver.v1.*;

import java.util.HashMap;
import java.util.Map;

public class EnvTest {

    @Test
    public void testConnection(){
        Driver driver = GraphDatabase.driver( "bolt://localhost:7687", AuthTokens.basic("neo4j", "root" ) );
        System.out.println("Server is up and Running");
        // find all the author names for a given  movie name
        String query = "MATCH (movie: Movie {title:$title})<-[:ACTED_IN]-(person:Person) RETURN person.name as actor";
        Map<String,Object> titleMap = new HashMap<>();
        titleMap.put("title","The Matrix");
        try{
            Session session = driver.session();
            StatementResult statementResult = session.run(query,titleMap);
            while(statementResult.hasNext()){
                System.out.println(statementResult.next().get("actor"));
            }
            session.close();
        }catch (Exception e){
            e.printStackTrace();
        }
        try {
            driver.close();
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

Result

INFO: Direct driver instance 99451533 created for server address localhost:7687
Server is up and Running
"Emil Eifrem"
"Hugo Weaving"
"Laurence Fishburne"
"Carrie-Anne Moss"
"Keanu Reeves"
May 14, 2019 3:45:49 PM org.neo4j.driver.internal.logging.JULogger info
INFO: Closing driver instance 99451533
May 14, 2019 3:45:49 PM org.neo4j.driver.internal.logging.JULogger info
INFO: Closing connection pool towards localhost:7687

Process finished with exit code 0

Each Result is in the type of _org.neo4j.driver.v1.Record_, Record is a form of ordered map and, as such, contained values can be accessed by either positional index or textual key.doc.

Record can either be node or relationships. When we retrieve data from the graph database, we either want to retrieve nodes(with properties and values) or a path contains nodes and relationships. Here are two small demos for retrieving nodes and paths.

5. Small Demo

Preparation: Let us create a DriverUtil class to wrap the manipulations on the driver

5.1 Retrieve Node.

Here is the sample code for querying a person by giving its name.

package com.neo4j.movies;

import Util.DriverUtil;
import org.junit.Test;
import org.neo4j.driver.v1.*;
import org.neo4j.driver.v1.types.Node;

import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import static org.junit.Assert.*;

public class FindPersonByName {

    public void findPersonByName(String queryName){
        Driver driver = DriverUtil.getDriver();
        String queryPersonByName = "MATCH (person:Person) WHERE person.name = $name RETURN person";
        Map<String,Object> map = new HashMap<>();
        map.put("name",queryName);
        try(Session session = driver.session()) {
            StatementResult statementResult  = session.run(queryPersonByName, map);
            while(statementResult.hasNext()){
                Record record = statementResult.next();
                List<Value> valueList = record.values();// Retrieve the values of the underlying map
                assertEquals(valueList.size(),1);
                // each value is a node actually, so convert to node type
                for(Value value: valueList){
                    Node node = value.asNode();
                    // iterate through node labels
                    Iterator<String> labels = node.labels().iterator();
                    System.out.println("Node labels");
                    while(labels.hasNext()){
                        System.out.println(labels.next());
                    }

                    // iterate through node property-value pairs
                    System.out.println("Node key-value pairs ");
                    Iterator<String> keys = node.keys().iterator();
                    while(keys.hasNext()){
                        String property = keys.next();
                        Object propertyValue = node.get(property);
                        System.out.println("property: "+ property);
                        System.out.println("propertyValue: "+ propertyValue);
                    }

                }
            }
        }catch (Exception e){
            e.printStackTrace();
        }


        try{
            DriverUtil.closeDriver();
        } catch (Exception e){
            e.printStackTrace();
        }
    }
    @Test
    public static void main(String[] args) {
        FindPersonByName fd = new findPersonByName();
        fd.findPersonByName("Emil Eifrem");
    }
}

Result

INFO: Direct driver instance 530653666 created for server address localhost:7687
Node labels
Person

Node key-value pairs
property: name
propertyValue: "Emil Eifrem"
property: born
propertyValue: 1978

INFO: Closing connection pool towards localhost:7687
Disconnected from the target VM, address: '127.0.0.1:57996', transport: 'socket'

Process finished with exit code 0

We can see the Result Object by debugging mode.

Smiley face

We can see that Record itself is an unordered Hash Map, and keys are the Strings of the Return Statement in SQL. And the Value object itself is also a HashMap.

If value itself is a node. it contains

  1. A List of labels
  2. A List of properties, where properties itself is also a hash map, mapping from property keys to property values.

For all their usages ,see document.

5.2 Retrieve Path(relationship).

Suppose we want to see if a person ACTED_IN a movie and what is his/her role in the movie. If that particular people does not ACTED_IN that movie, return false.

e.g “Keanu Reeves” ACTED_IN “Johnny Mnemonic” as “Johnny Mnemonic”

Smiley face

Lets see the path Object.

It contains:

  1. An ArrayList of nodes
  2. An ArrayList of relationships
  3. An ArrayList of segments which contains the start node, relation and the end node.
Smiley face
package com.neo4j.movies;

import Util.DriverUtil;
import org.junit.Test;
import org.neo4j.driver.v1.*;
import org.neo4j.driver.v1.types.Node;
import org.neo4j.driver.v1.types.Path;
import org.neo4j.driver.v1.types.Relationship;

import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

public class FindRolesByPersonNameAndMovieName {
    @Test
    public void findRolesByPersonNameAndMovieName(String actorName, String movieName){
        Driver driver = DriverUtil.getDriver();
        String queryRoles = "MATCH p =(person:Person)-[ACTED_IN]->(movie:Movie) WHERE person.name = $actorName " +
                                    "AND movie.title = $movieName RETURN p ";
        Map<String,Object> parameters = new HashMap<>();
        parameters.put("actorName",actorName);
        parameters.put("movieName",movieName);

        try(Session session = driver.session()){
            StatementResult statementResult  = session.run(queryRoles,parameters);
            System.out.println("*****relationship*******");
            while(statementResult.hasNext()){
                Record record = statementResult.next();
                List<Value> valuesList = record.values();
                // if the movie and actor do not match each other, no searching result.
                if(valuesList == null || valuesList.size() == 0) return;
                // find the relationship between the movie node and person node
                Path path = valuesList.get(0).asPath();
                // find all the relationships(edges) along the path
                Iterator<Relationship> relationships = path.relationships().iterator();
                // find all the nodes along the path
                Iterator<Node> nodes = path.nodes().iterator();
                // iterate edges along the path
                while(relationships.hasNext()){
                    Relationship relationship = relationships.next();
                    relationship.startNodeId();
                    relationship.endNodeId();
                    String relationType = relationship.type();
                    System.out.println("start from Node Id: "+ relationship.startNodeId());
                    System.out.println("end from Node Id: "+ relationship.endNodeId());
                    System.out.println("The relation type is:" +relationType);
                    System.out.println("RelationShip key value pairs");
                    Iterator<String> relationKeys = relationship.keys().iterator();
                    while(relationKeys.hasNext()){
                        String relationKey = relationKeys.next();
                        Object relationValue = relationship.get(relationKey).get(0);
                        System.out.println(relationKey +":" +relationValue);
                    }
                }

                // iterate all nodes along the path
                while(nodes.hasNext()){
                    System.out.println("*****Node*******");
                    Node node = nodes.next();
                    System.out.println("Node Id: " + node.id());
                    Iterator<String> labels = node.labels().iterator();
                    System.out.println("Node labels");
                    while(labels.hasNext()){
                        System.out.println(labels.next());
                    }

                    // iterate through node property-value pairs
                    System.out.println("Node key-value pairs ");
                    Iterator<String> keys = node.keys().iterator();
                    while(keys.hasNext()){
                        String property = keys.next();
                        Object propertyValue = node.get(property);
                        System.out.println(property+":"+propertyValue);
                    }
                }

            }

        }catch (Exception e){
            e.printStackTrace();
        }finally {
            DriverUtil.closeDriver();
        }
    }

    public static void main(String[] args) {
        FindRolesByPersonNameAndMovieName findRole = new FindRolesByPersonNameAndMovieName();
        findRole.findRolesByPersonNameAndMovieName("Keanu Reeves","Johnny Mnemonic");
    }
}

Result

*****relationship*******
start from Node Id: 1
end from Node Id: 161
The relation type is:ACTED_IN
RelationShip key value pairs
roles:"Johnny Mnemonic"
*****Node*******
Node Id: 1
Node labels
Person
Node key-value pairs
name:"Keanu Reeves"
born:1964
*****Node*******
Node Id: 161
Node labels
Movie
Node key-value pairs
tagline:"The hottest data on earth. In the coolest head in town"
title:"Johnny Mnemonic"
released:1995

Notice that: the return type is a path, So, in CQL, We name the path as p. If we want to return all, Using Return *, see CQL manual,link.

6. OGM Mapping And Mapping to JSON

To be continued.


Author: Liang Tan
Reprint policy: All articles in this blog are used except for special statements CC BY 4.0 reprint polocy. If reproduced, please indicate source Liang Tan !
 Previous
DesignPattern -  Iterator Pattern DesignPattern - Iterator Pattern
1. Definition:Let us first look at the strict definition of Decorator Pattern, Iterator Pattern provides a way to acces
2019-05-16 Liang Tan
Next 
How to Design your Own Online Shopping Website like amazon -- DB design How to Design your Own Online Shopping Website like amazon -- DB design
1. IntroductionBefore designing the database for our small online shopping system, let’s review three normalization form
2019-05-13
  TOC