Often in the life of developer’s life there is a scenario where using a relational database tends to get complicated or sometimes even slow – especially when there are fragments with multiple relationships or multiple connections present. This often leads to complex database queries or desperate software engineers trying to handle those problems with their ORM framework.

A possible solution might be to switch from a relational database to a graph database – and – neo4j is our tool of choice here. In the following tutorial we’re going to implement several examples to demonstrate the strengths of a graph database .. from a route planner to a social graph.

Prerequisites

You need to meet the following requirements to run the samples below ..

Adding neo4j to a Maven Project

First a new Maven project …

  • Create a new simple Maven project using your IDE or

    mvn archetype:generate
  • Add the following dependencies needed for neo4j

    <dependency>
     <groupId>org.neo4j</groupId>
     <artifactId>neo4j</artifactId>
     <version>1.5</version>
    </dependency>
  • The neo4j community edition is licensed under the GPLv3 license

Example: Using the Indexer

Often we want to search for a node with a specific property e.g. an id or another attribute without having to traverse the node graph. Luckily for us neo4j comes with my favourite indexer, Lucene and allows to find a node in no time by searching for its indexed properties.

In the following example, we’re creating two nodes – each node has its properties name and id – and we’re adding those properties to the Lucene index so that we’re able to search for these properties..

lucene index
Figure 1. Referencing nodes via attributes in the Lucene index

This is my sample named IndexSearchExample

package com.hascode.tutorial;

import static com.hascode.tutorial.GraphUtil.cleanUp;
import static com.hascode.tutorial.GraphUtil.registerShutdownHook;

import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.Transaction;
import org.neo4j.graphdb.index.Index;
import org.neo4j.kernel.EmbeddedGraphDatabase;

public class IndexSearchExample {
	private static String DB_PATH = "/tmp/neo4j";

	public static void main(final String[] args) {
		GraphDatabaseService graphDb = new EmbeddedGraphDatabase(DB_PATH);
		Index<Node> nodeIndex = graphDb.index().forNodes("nodes");
		registerShutdownHook(graphDb);

		Transaction tx = graphDb.beginTx();
		try {
			// cleanup first for this tutorial
			cleanUp(graphDb, nodeIndex);

			Node userNode1 = graphDb.createNode();
			userNode1.setProperty("id", 1);
			userNode1.setProperty("name", "Peter");
			nodeIndex.add(userNode1, "id", 1);
			nodeIndex.add(userNode1, "name", "Peter");

			Node userNode2 = graphDb.createNode();
			userNode2.setProperty("id", 2);
			userNode2.setProperty("name", "Ray");
			nodeIndex.add(userNode2, "id", 2);
			nodeIndex.add(userNode2, "name", "Ray");

			tx.success();

			System.out.println("searching for user with id=2..");
			Node user = nodeIndex.get("id", 2).getSingle();
			System.out.println("The name of the user with id=2 is: "
					+ user.getProperty("name"));

			System.out.println("searching for user with name=Peter..");
			Node user2 = nodeIndex.get("name", "Peter").getSingle();
			System.out.println("The id of the user with name=Peter is: "
					+ user2.getProperty("id"));
		} finally {
			tx.finish();
			graphDb.shutdown();
		}

	}
}

I’ve put two convenience methods for this tutorial in a utility class named GraphUtil – it’s just to recreate the node graph and the index on every run. I’m using it in the other examples, too..

package com.hascode.tutorial;

import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.Relationship;
import org.neo4j.graphdb.index.Index;

public class GraphUtil {
	public static void cleanUp(final GraphDatabaseService graphDb,
			final Index<Node> nodeIndex) {
		for (Node node : graphDb.getAllNodes()) {
			for (Relationship rel : node.getRelationships()) {
				rel.delete();
			}
			nodeIndex.remove(node);
			node.delete();
		}

	}

	public static void registerShutdownHook(final GraphDatabaseService graphDb) {
		Runtime.getRuntime().addShutdownHook(new Thread() {
			@Override
			public void run() {
				graphDb.shutdown();
			}
		});
	}
}

Running the example you should see an output similar to this:

searching for user with id=2..
The name of the user with id=2 is: Ray
searching for user with name=Peter..
The id of the user with name=Peter is: 1

Example: Node Traversal

In the next example we want to create – and link some nodes and afterwards traverse them. Nodes with two properties id and name may have a relationship of type “KNOWS”.

A graph of people knowing each other image::people-graph-relations.png[]

I have created an enum named RelTypes that implements RelationshipType. This is where the relations are defined

package com.hascode.tutorial;

import org.neo4j.graphdb.RelationshipType;

public enum RelTypes implements RelationshipType {
	KNOWS, LEADS_TO
}

This is my sample class: NodeTraversal

package com.hascode.tutorial;

import static com.hascode.tutorial.GraphUtil.registerShutdownHook;

import org.neo4j.graphdb.Direction;
import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.Relationship;
import org.neo4j.graphdb.ReturnableEvaluator;
import org.neo4j.graphdb.StopEvaluator;
import org.neo4j.graphdb.Transaction;
import org.neo4j.graphdb.Traverser;
import org.neo4j.graphdb.Traverser.Order;
import org.neo4j.kernel.EmbeddedGraphDatabase;

public class NodeTraversalExample {
	private static String DB_PATH = "/tmp/neo4j";

	public static void main(final String[] args) {
		GraphDatabaseService graphDb = new EmbeddedGraphDatabase(DB_PATH);
		registerShutdownHook(graphDb);

		Transaction tx = graphDb.beginTx();
		try {
			Node peterNode = graphDb.createNode();
			peterNode.setProperty("id", 1);
			peterNode.setProperty("name", "Peter");

			Node rayNode = graphDb.createNode();
			rayNode.setProperty("id", 2);
			rayNode.setProperty("name", "Ray");

			Node egonNode = graphDb.createNode();
			egonNode.setProperty("id", 3);
			egonNode.setProperty("name", "Egon");

			Node winstonNode = graphDb.createNode();
			winstonNode.setProperty("id", 4);
			winstonNode.setProperty("name", "Winston");

			Node slimerNode = graphDb.createNode();
			slimerNode.setProperty("id", 5);
			slimerNode.setProperty("name", "Slimer");

			Relationship rel1 = peterNode.createRelationshipTo(rayNode,
					RelTypes.KNOWS);
			rel1.setProperty("visibility", "public");

			Relationship rel2 = rayNode.createRelationshipTo(egonNode,
					RelTypes.KNOWS);
			rel2.setProperty("visibility", "hidden");

			Relationship rel3 = rayNode.createRelationshipTo(winstonNode,
					RelTypes.KNOWS);
			rel3.setProperty("visibility", "public");

			Relationship rel4 = winstonNode.createRelationshipTo(slimerNode,
					RelTypes.KNOWS);
			rel4.setProperty("visibility", "public");

			tx.success();

			System.out.println("traversing nodes for Peter's acquaintances..");
			Traverser acquaintanceTraverser = getAcquaintances(peterNode);
			for (Node acquaintanceNode : acquaintanceTraverser) {
				System.out.println("Peter knows "
						+ acquaintanceNode.getProperty("name") + " (id: "
						+ acquaintanceNode.getProperty("id") + ") at depth: "
						+ acquaintanceTraverser.currentPosition().depth());
			}
		} finally {
			tx.finish();
		}

		graphDb.shutdown();
	}

	private static Traverser getAcquaintances(final Node personNode) {
		return personNode.traverse(Order.BREADTH_FIRST,
				StopEvaluator.END_OF_GRAPH,
				ReturnableEvaluator.ALL_BUT_START_NODE, RelTypes.KNOWS,
				Direction.OUTGOING);
	}
}

Running the sample, the following output should appear

traversing nodes for Peter's acquaintances..
Peter knows Ray (id: 2) at depth: 1
Peter knows Egon (id: 3) at depth: 2
Peter knows Winston (id: 4) at depth: 2
Peter knows Slimer (id: 5) at depth: 3

Example: Node Filtering

In the following example we’re traversing the nodes given some additional criteria – only relations with a property visibility=public should be traversed..

people graph
Figure 2. Graph of people with a visibility attribute

This is my example – FilteredNodeTraversalExample

package com.hascode.tutorial;

import static com.hascode.tutorial.GraphUtil.registerShutdownHook;

import org.neo4j.graphdb.Direction;
import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.Relationship;
import org.neo4j.graphdb.ReturnableEvaluator;
import org.neo4j.graphdb.StopEvaluator;
import org.neo4j.graphdb.Transaction;
import org.neo4j.graphdb.TraversalPosition;
import org.neo4j.graphdb.Traverser;
import org.neo4j.graphdb.Traverser.Order;
import org.neo4j.kernel.EmbeddedGraphDatabase;

public class FilteredNodeTraversalExample {
	private static String DB_PATH = "/tmp/neo4j";

	public static void main(final String[] args) {
		GraphDatabaseService graphDb = new EmbeddedGraphDatabase(DB_PATH);
		registerShutdownHook(graphDb);

		Transaction tx = graphDb.beginTx();
		try {
			Node peterNode = graphDb.createNode();
			peterNode.setProperty("id", 1);
			peterNode.setProperty("name", "Peter");

			Node rayNode = graphDb.createNode();
			rayNode.setProperty("id", 2);
			rayNode.setProperty("name", "Ray");

			Node egonNode = graphDb.createNode();
			egonNode.setProperty("id", 3);
			egonNode.setProperty("name", "Egon");

			Node winstonNode = graphDb.createNode();
			winstonNode.setProperty("id", 4);
			winstonNode.setProperty("name", "Winston");

			Node slimerNode = graphDb.createNode();
			slimerNode.setProperty("id", 5);
			slimerNode.setProperty("name", "Slimer");

			Relationship rel1 = peterNode.createRelationshipTo(rayNode,
					RelTypes.KNOWS);
			rel1.setProperty("visibility", "public");

			Relationship rel2 = rayNode.createRelationshipTo(egonNode,
					RelTypes.KNOWS);
			rel2.setProperty("visibility", "hidden");

			Relationship rel3 = rayNode.createRelationshipTo(winstonNode,
					RelTypes.KNOWS);
			rel3.setProperty("visibility", "public");

			Relationship rel4 = winstonNode.createRelationshipTo(slimerNode,
					RelTypes.KNOWS);
			rel4.setProperty("visibility", "public");

			tx.success();

			System.out
					.println("traversing nodes for Peter's public acquaintances..");
			Traverser acquaintanceTraverser = getAcquaintances(peterNode);
			for (Node acquaintanceNode : acquaintanceTraverser) {
				System.out.println("Peter knows "
						+ acquaintanceNode.getProperty("name") + " (id: "
						+ acquaintanceNode.getProperty("id") + ") at depth: "
						+ acquaintanceTraverser.currentPosition().depth());
			}
		} finally {
			tx.finish();
		}

		graphDb.shutdown();
	}

	private static Traverser getAcquaintances(final Node personNode) {
		return personNode.traverse(Order.BREADTH_FIRST,
				StopEvaluator.END_OF_GRAPH, new ReturnableEvaluator() {
					@Override
					public boolean isReturnableNode(
							final TraversalPosition currentPos) {
						return !currentPos.isStartNode()
								&& currentPos.lastRelationshipTraversed()
										.hasProperty("visibility")
								&& "public".equals(currentPos
										.lastRelationshipTraversed()
										.getProperty("visibility"));
					}
				}, RelTypes.KNOWS, Direction.OUTGOING);
	}
}

And this is the expected output

traversing nodes for Peter's public acquaintances..
Peter knows Ray (id: 2) at depth: 1
Peter knows Winston (id: 4) at depth: 2
Peter knows Slimer (id: 5) at depth: 3

Example: Building a Route Planner

In the following example we’re simulating a railway network – railway stations are connected with other railway stations and each connection between two stations has a property: the distance (in miles).

We’re using Dijkstras algorithm to calculate the shortest route from London to Bristol and Northampton to Brighton here.

railway network nodes
Figure 3. Railway Network Nodes

And this is the sample code

package com.hascode.tutorial;

import static com.hascode.tutorial.GraphUtil.registerShutdownHook;

import org.neo4j.graphalgo.GraphAlgoFactory;
import org.neo4j.graphalgo.PathFinder;
import org.neo4j.graphalgo.WeightedPath;
import org.neo4j.graphdb.Direction;
import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.Relationship;
import org.neo4j.graphdb.Transaction;
import org.neo4j.graphdb.index.Index;
import org.neo4j.kernel.EmbeddedGraphDatabase;
import org.neo4j.kernel.Traversal;

public class RailroadExample {
	private static String DB_PATH = "/tmp/neo4j";

	public static void main(final String[] args) {
		GraphDatabaseService graphDb = new EmbeddedGraphDatabase(DB_PATH);
		registerShutdownHook(graphDb);
		Index<Node> nodeIndex = graphDb.index().forNodes("nodes");

		Transaction tx = graphDb.beginTx();
		try {
			Node londonNode = graphDb.createNode();
			londonNode.setProperty("name", "London");
			nodeIndex.add(londonNode, "name", "London");

			Node brightonNode = graphDb.createNode();
			brightonNode.setProperty("name", "Brighton");
			nodeIndex.add(brightonNode, "name", "Brighton");

			Node portsmouthNode = graphDb.createNode();
			portsmouthNode.setProperty("name", "Portsmouth");
			nodeIndex.add(portsmouthNode, "name", "Portsmouth");

			Node bristolNode = graphDb.createNode();
			bristolNode.setProperty("name", "Bristol");
			nodeIndex.add(bristolNode, "name", "Bristol");

			Node oxfordNode = graphDb.createNode();
			oxfordNode.setProperty("name", "Oxford");
			nodeIndex.add(oxfordNode, "name", "Oxford");

			Node gloucesterNode = graphDb.createNode();
			gloucesterNode.setProperty("name", "Gloucester");
			nodeIndex.add(gloucesterNode, "name", "Gloucester");

			Node northamptonNode = graphDb.createNode();
			northamptonNode.setProperty("name", "Northampton");
			nodeIndex.add(northamptonNode, "name", "Northampton");

			Node southamptonNode = graphDb.createNode();
			southamptonNode.setProperty("name", "Southampton");
			nodeIndex.add(southamptonNode, "name", "Southampton");

			// london -> brighton ~ 52mi
			Relationship r1 = londonNode.createRelationshipTo(brightonNode,
					RelTypes.LEADS_TO);
			r1.setProperty("distance", 52);

			// brighton -> portsmouth ~ 49mi
			Relationship r2 = brightonNode.createRelationshipTo(portsmouthNode,
					RelTypes.LEADS_TO);
			r2.setProperty("distance", 49);

			// portsmouth -> southampton ~ 20mi
			Relationship r3 = portsmouthNode.createRelationshipTo(
					southamptonNode, RelTypes.LEADS_TO);
			r3.setProperty("distance", 20);

			// london -> oxford ~95mi
			Relationship r4 = londonNode.createRelationshipTo(oxfordNode,
					RelTypes.LEADS_TO);
			r4.setProperty("distance", 95);

			// oxford -> southampton ~66mi
			Relationship r5 = oxfordNode.createRelationshipTo(southamptonNode,
					RelTypes.LEADS_TO);
			r5.setProperty("distance", 66);

			// oxford -> northampton ~45mi
			Relationship r6 = oxfordNode.createRelationshipTo(northamptonNode,
					RelTypes.LEADS_TO);
			r6.setProperty("distance", 45);

			// northampton -> bristol ~114mi
			Relationship r7 = northamptonNode.createRelationshipTo(bristolNode,
					RelTypes.LEADS_TO);
			r7.setProperty("distance", 114);

			// southampton -> bristol ~77mi
			Relationship r8 = southamptonNode.createRelationshipTo(bristolNode,
					RelTypes.LEADS_TO);
			r8.setProperty("distance", 77);

			// northampton -> gloucester ~106mi
			Relationship r9 = northamptonNode.createRelationshipTo(
					gloucesterNode, RelTypes.LEADS_TO);
			r9.setProperty("distance", 106);

			// gloucester -> bristol ~35mi
			Relationship r10 = gloucesterNode.createRelationshipTo(bristolNode,
					RelTypes.LEADS_TO);
			r10.setProperty("distance", 35);

			tx.success();

			System.out
					.println("searching for the shortest route from London to Bristol..");
			PathFinder<WeightedPath> finder = GraphAlgoFactory.dijkstra(
					Traversal.expanderForTypes(RelTypes.LEADS_TO,
							Direction.BOTH), "distance");

			WeightedPath path = finder.findSinglePath(londonNode, bristolNode);
			System.out.println("London - Bristol with a distance of: "
					+ path.weight() + " and via: ");
			for (Node n : path.nodes()) {
				System.out.print(" " + n.getProperty("name"));
			}

			System.out
					.println("\nsearching for the shortest route from Northampton to Brighton..");
			path = finder.findSinglePath(northamptonNode, brightonNode);
			System.out.println("Northampton - Brighton with a distance of: "
					+ path.weight() + " and via: ");
			for (Node n : path.nodes()) {
				System.out.print(" " + n.getProperty("name"));
			}

		} finally {
			tx.finish();
		}

		graphDb.shutdown();
	}
}

Running the code gives us the following output

searching for the shortest route from London to Bristol..
London - Bristol with a distance of: 198.0 and via:
 London Brighton Portsmouth Southampton Bristol
searching for the shortest route from Northampton to Brighton..
Northampton - Brighton with a distance of: 180.0 and via:
 Northampton Oxford Southampton Portsmouth Brighton

Example: Mapping Users to Roles to Permissions

As another example we’re going to implement a system that assigns users to roles and permissions to roles.

There are three different roles: guest, user and admin and three permissions: read, write and administer.

We’re now building a graph to map the different permissions but you might ask where there is the advantage of using a graph for this?

We could make the scenario a bit more difficult and say that there are combined roles .. e.g. role root is a part of the role admin and the permissions read, write and administer are all parts of a permission named godmode – using a graph there we only need to descend the graph until we’ve got all permissions for the user mapped by the different possible paths in the graph.

user roles
Figure 4. User-Roles-Permissions mapped using a Graph

We’re using a fresh enum to define our relation types here UserRelTypes

package com.hascode.tutorial;

import org.neo4j.graphdb.RelationshipType;

public enum UserRelTypes implements RelationshipType {
	MEMBER_OF, HAS_ROLE, HAS_PERMISSION
}

Now to create the node structure

package com.hascode.tutorial;

import static com.hascode.tutorial.GraphUtil.cleanUp;
import static com.hascode.tutorial.GraphUtil.registerShutdownHook;

import org.neo4j.graphdb.Direction;
import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.ReturnableEvaluator;
import org.neo4j.graphdb.StopEvaluator;
import org.neo4j.graphdb.Transaction;
import org.neo4j.graphdb.Traverser;
import org.neo4j.graphdb.index.Index;
import org.neo4j.kernel.EmbeddedGraphDatabase;

public class UserRolePermissionExample {
	private static String DB_PATH = "/tmp/neo4j";

	public static void main(final String[] args) {
		GraphDatabaseService graphDb = new EmbeddedGraphDatabase(DB_PATH);
		registerShutdownHook(graphDb);
		Index<Node> nodeIndex = graphDb.index().forNodes("nodes");

		Transaction tx = graphDb.beginTx();
		try {
			// cleanup first for this tutorial
			cleanUp(graphDb, nodeIndex);

			// 1. define possible permissions
			// permission:read
			Node permissionRead = graphDb.createNode();
			permissionRead.setProperty("permission", "read");
			nodeIndex.add(permissionRead, "permission", "read");

			// permission:write
			Node permissionWrite = graphDb.createNode();
			permissionWrite.setProperty("permission", "write");
			nodeIndex.add(permissionWrite, "permission", "write");

			// permission:administer
			Node permissionAdminister = graphDb.createNode();
			permissionAdminister.setProperty("permission", "administer");
			nodeIndex.add(permissionAdminister, "permission", "administer");

			// 2. define possible roles
			// role:guest
			Node roleGuest = graphDb.createNode();
			roleGuest.setProperty("role", "guest");
			nodeIndex.add(roleGuest, "role", "guest");

			// role:user
			Node roleUser = graphDb.createNode();
			roleUser.setProperty("role", "user");
			nodeIndex.add(roleUser, "role", "user");

			Node roleAdmin = graphDb.createNode();
			roleAdmin.setProperty("role", "admin");
			nodeIndex.add(roleAdmin, "role", "admin");

			// 3. assign permissions to roles
			// guests are only allowed to read
			roleGuest.createRelationshipTo(permissionRead,
					UserRelTypes.HAS_PERMISSION);

			// users my read and write
			roleUser.createRelationshipTo(permissionRead,
					UserRelTypes.HAS_PERMISSION);
			roleUser.createRelationshipTo(permissionWrite,
					UserRelTypes.HAS_PERMISSION);

			// administrators may read, write and administer
			roleAdmin.createRelationshipTo(permissionRead,
					UserRelTypes.HAS_PERMISSION);
			roleAdmin.createRelationshipTo(permissionWrite,
					UserRelTypes.HAS_PERMISSION);
			roleAdmin.createRelationshipTo(permissionAdminister,
					UserRelTypes.HAS_PERMISSION);

			// 4. finally create some users and assign roles
			// egon is a guest
			Node egon = graphDb.createNode();
			egon.setProperty("name", "Egon");
			nodeIndex.add(egon, "name", "Egon");
			egon.createRelationshipTo(roleGuest, UserRelTypes.HAS_ROLE);

			// winston is a user
			Node winston = graphDb.createNode();
			winston.setProperty("name", "Winston");
			nodeIndex.add(winston, "name", "Winston");
			winston.createRelationshipTo(roleUser, UserRelTypes.HAS_ROLE);

			// slimer is - of course - an admin
			Node slimer = graphDb.createNode();
			slimer.setProperty("name", "Slimer");
			nodeIndex.add(slimer, "name", "Slimer");
			slimer.createRelationshipTo(roleAdmin, UserRelTypes.HAS_ROLE);

			tx.success();

			System.out
					.println("Looking up permissions for user with name=Winston");
			Node userWinston = nodeIndex.get("name", "Winston").getSingle();
			Traverser permissionTraverser = getPermissionTraverser(userWinston);
			printPermissions(userWinston, permissionTraverser);

			System.out
					.println("Looking up permissions for user with name=Slimer");
			Node userSlimer = nodeIndex.get("name", "Slimer").getSingle();
			permissionTraverser = getPermissionTraverser(userSlimer);
			printPermissions(userSlimer, permissionTraverser);
		} finally {
			tx.finish();
		}

		graphDb.shutdown();
	}

	private static void printPermissions(final Node userNode,
			final Traverser permissionTraverser) {
		final String userName = (String) userNode.getProperty("name");
		for (Node node : permissionTraverser) {
			if (node.hasProperty("role")) {
				System.out.println(userName + " has the role: "
						+ node.getProperty("role"));
			}
			if (node.hasProperty("permission")) {
				System.out.println(userName + " has permission: "
						+ node.getProperty("permission") + " at depth: "
						+ (permissionTraverser.currentPosition().depth() - 1));
			}
		}
	}

	private static Traverser getPermissionTraverser(final Node userNode) {
		return userNode.traverse(Traverser.Order.DEPTH_FIRST,
				StopEvaluator.END_OF_GRAPH,
				ReturnableEvaluator.ALL_BUT_START_NODE, UserRelTypes.HAS_ROLE,
				Direction.OUTGOING, UserRelTypes.HAS_PERMISSION,
				Direction.OUTGOING);
	}
}

And this is the output

Looking up permissions for user with name=Winston
Winston has the role: user
Winston has permission: read at depth: 1
Winston has permission: write at depth: 1
Looking up permissions for user with name=Slimer
Slimer has the role: admin
Slimer has permission: read at depth: 1
Slimer has permission: write at depth: 1
Slimer has permission: administer at depth: 1

Tutorial Sources

I have put the source from this tutorial on my GitHub repository – download it there or check it out using Git:

git clone https://github.com/hascode/neo4j-tutorial.git

yED Graph Editor

All the graph drawing in this tutorial were made using the free yED graph editor from yWorks – it’s really easy and comfortable to use and has some nice features!

You’re able to download it here or simply start the editor from here using Java Web Start.

yed withgraph
Figure 5. The yED Graph Editor

Troubleshooting

  • “Exception in thread “main” java.util.NoSuchElementException: More than one element in org.neo4j.index.impl.lucene.LuceneIndex$1@12789d2. First element is ‘Node[2]‘ and the second element is ‘Node[4]‘
    at org.neo4j.helpers.collection.IteratorUtil.singleOrNull(IteratorUtil.java:116)
    at org.neo4j.index.impl.lucene.IdToEntityIterator.getSingle(IdToEntityIterator.java:88)
    at org.neo4j.index.impl.lucene.IdToEntityIterator.getSingle(IdToEntityIterator.java:32)
    at com.hascode.tutorial.IndexSearchExample.main(IndexSearchExample.java:45)”
    – if you’re running the tutorial sources or you’re just experimenting – you eventually might need to reset your graph or your node index – the following method helps you there

    public void cleanUp(final GraphDatabaseService graphDb,
     final Index<Node> nodeIndex) {
     for (Node node : graphDb.getAllNodes()) {
     for (Relationship rel : node.getRelationships()) {
     rel.delete();
     }
     nodeIndex.remove(node);
     node.delete();
     }