Accessing Data with Neo4j :: Learn how to persist objects and relationships in Neo4j's NoSQL data store.
Shell Batchfile Java

README.adoc

tags projects
spring-data
neo4j
spring-data-neo4j

This guide walks you through the process of using Spring Data Neo4j to build an application that stores data in and retrieves it from Neo4j, a graph-based database.

What you’ll build

You’ll use Neo4j’s NoSQL graph-based data store to build an embedded Neo4j server, store entities and relationships, and develop queries.

Standing up a Neo4j server

Before you can build a this application, you need to set up a Neo4j server.

Neo4j has an open source server you can install for free:

On a Mac, just type:

$ brew install neo4j

Once you installed, launch it with it’s default settings:

$ neo4j start

You should see a message like this:

Starting Neo4j.
Started neo4j (pid 96416). By default, it is available at http://localhost:7474/
There may be a short delay until the server is ready.
See /usr/local/Cellar/neo4j/3.0.6/libexec/logs/neo4j.log for current status.

By default, Neo4j has a username/password of neo4j/neo4j. However, it requires that the new account password be changed. To do so, execute the following command:

$ curl -v -u neo4j:neo4j -X POST localhost:7474/user/neo4j/password -H 'Content-type:application/json' -d '{"password":"secret"}'

This changes the password from neo4j to secret (something to NOT DO in production!) With that completed, you should be ready to run this guide.

Define a simple entity

Neo4j captures entities and their relationships, with both aspects being of equal importance. Imagine you are modeling a system where you store a record for each person. But you also want to track a person’s co-workers (teammates in this example). With Neo4j, you can capture all that with some simple annotations.

src/main/java/hello/Person.java

link:complete/src/main/java/hello/Person.java[]

Here you have a Person class that has only one attribute, the name.

Note
In this guide, the typical getters and setters are omitted for brevity.

The Person class is annotated @NodeEntity. When Neo4j stores it, it results in the creation of a new node. This class also has an id marked @GraphId. Neo4j uses @GraphId internally to track the data.

The next important piece is the set of teammates. It is a simple Set<Person>, but marked up as @Relationship. This means that every member of this set is expected to also exist as a separate Person node. Note how the direction is set to UNDIRECTED. This means that when you query the TEAMMATE relationship, Spring Data Neo4j will ignore the direction of the relationship.

With the worksWith() method, you can easily link people together.

Finally, you have a convenient toString() method to print out the person’s name and that person’s co-workers.

Create simple queries

Spring Data Neo4j is focused on storing data in Neo4j. But it inherits functionality from the Spring Data Commons project, including the ability to derive queries. Essentially, you don’t have to learn the query language of Neo4j, but can simply write a handful of methods and the queries are written for you.

To see how this works, create an interface that queries Person nodes.

src/main/java/hello/PersonRepository.java

link:complete/src/main/java/hello/PersonRepository.java[]

PersonRepository extends the GraphRepository interface and plugs in the type it operates on: Person. Out-of-the-box, this interface comes with many operations, including standard CRUD (create-read-update-delete) operations.

But you can define other queries as needed by simply declaring their method signature. In this case, you added findByName, which seeks nodes of type Person and finds the one that matches on name. You also have findByTeammatesName, which looks for a Person node, drills into each entry of the teammates field, and matches based on the teammate’s name.

Permissions to access Neo4j

Neo4j Community Edition requires credentials to access it. This can be configured with a couple properties.

link:complete/src/main/resources/application.properties[]

This includes the default username neo4j and the newly set password secret we picked earlier.

Warning
Do NOT store real credentials in your source repository. Instead, configure them in your runtime using Spring Boot’s property overrides.

With this in place, let’s wire this up and see what it looks like!

Create an Application class

Here you create an Application class with all the components.

src/main/java/hello/Application.java

link:complete/src/main/java/hello/Application.java[]

Spring Boot will handle those repositories automatically as long as they are included in the same package (or a sub-package) of your @SpringBootApplication class. For more control over the registration process, you can use the @EnableNeo4jRepositories annotation.

Note
By default, @EnableNeo4jRepositories will scan the current package for any interfaces that extend one of Spring Data’s repository interfaces. Use it’s basePackageClasses=MyRepository.class to safely tell Spring Data Neo4j to scan a different root package by type if your project layout has multiple projects and its not finding your repositories.

Logging output is displayed. The service should be up and running within a few seconds.

You autowire an instance of PersonRepository that you defined earlier. Spring Data Neo4j will dynamically implement that interface and will plug in the needed query code to meet the interface’s obligations.

The public static void main uses Spring Boot’s SpringApplication.run() to launch the application and invoke the CommandLineRunner that builds the relationships.

In this case, you create three local Person s, Greg, Roy, and Craig. Initially, they only exist in memory. It’s also important to note that no one is a teammate of anyone (yet).

At first, you find Greg and indicate that he works with Roy and Craig, then persist him again. Remember, the teammate relationship was marked as UNDIRECTED, that is, bidirectional. That means that Roy and Craig will have been updated as well.

That’s why when you need to update Roy, it’s critical that you fetch that record from Neo4j first. You need the latest status on Roy’s teammates before adding Craig to the list.

Why is there no code that fetches Craig and adds any relationships? Because you already have! Greg earlier tagged Craig as a teammate, and so did Roy. That means there is no need to update Craig’s relationships again. You can see it as you iterate over each team member and print their information to the console.

Finally, check out that other query where you look backwards, answering the question "who works with whom?"

You should see something like this (with other stuff like queries as well):

Before linking up with Neo4j...
	Greg's teammates => []
	Roy's teammates => []
	Craig's teammates => []

Lookup each person by name...
	Greg's teammates => [Roy, Craig]
	Roy's teammates => [Greg, Craig]
	Craig's teammates => [Roy, Greg]

You can see from the output that initially no one is connected by any relationship. Then after adding people in, they are tied together. Finally, you can see the handy query that looks up people based on teammate.

Summary

Congratulations! You just set up an embedded Neo4j server, stored some simple, related entities, and developed some quick queries.

Note
If you’re interesting in exposing Neo4j repositories with a hypermedia-based RESTful front end with little effort, you might want to read Accessing Neo4j Data with REST.