Neo4j Graph Database Tutorial: How to build a Route Planner and other Examples
January 20th, 2012 by Micha KopsOften 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.
Contents
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..
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”.
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..
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.
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.
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 Bitbucket repository – download it there or check it out using Mercurial:
hg clone https://bitbucket.org/hascode/neo4j-tutorial
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.
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 therepublic 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(); }
Resources
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();
}
}
}
Tags: Algorithm, dijkstra, graph, graph editor, indexer, lucene, neo4j, node, route
January 20th, 2012 at 9:09 pm
Thanks for your work on this example. Did you test the route planner on real world data? Because I guess it (dijkstra and your ram/cpu) won’t scale beyond the size of a city with this approach … would be nice if you can try it though :) (importing some osm etc)
January 20th, 2012 at 9:15 pm
You’re probably right but it sounds interesting as an experiment indeed :)
January 31st, 2012 at 10:51 pm
The depth reported for NodeTraversalExample and FilteredNodeTraversalExample seems to be wrong, It always reports depth of 3. For NodeTraversalExample I made some changes to the traverser
Traverser friendsTraverser = getFriends( peterNode );
for ( Node friendNode : friendsTraverser )
{
System.out.println( “Peter knows ” +
friendNode.getProperty( “name” ) + ” (” +
friendNode.getProperty(“id”) + “) at depth ” +
friendsTraverser.currentPosition().depth()
);
}
private static Traverser getFriends( final Node personNode )
{
return personNode.traverse(
Order.BREADTH_FIRST,
stopEvaluator,
ReturnableEvaluator.ALL_BUT_START_NODE,
RelTypes.KNOWS,
Direction.OUTGOING );
}
and get the following which is more what I expected (I’m assuming depth is distance away from start node):
traversing nodes for Peter’s acquaintances..
Peter knows Ray (2) at depth 1
Peter knows Egon (3) at depth 2
Peter knows Winston (4) at depth 2
Peter knows Slimer (5) at depth 3
February 1st, 2012 at 7:17 pm
thanks a lot for mentioning! .. somehow the findAllNodes method has slipped into those two examples :)
February 3rd, 2012 at 3:57 pm
Awesome tutorial, congratulations! I’m looking for some weeks for an good introductions!
February 12th, 2012 at 6:35 am
A very good example. yED graphing utility seems to be very useful for my purposes. Many thanks for both of these.
August 28th, 2012 at 12:26 pm
Hi micha!
Thanks for your tutorial, I like it!
I started with yED and find the resulting .graphml very complicated.
Then I used your tutorial sources and things were much clearer.
Now I’m wonderning: Has you a solution to “generate?” the .graphml sources from a neoDB to be edited by yED?
Now I’m windering again: How could I update the neoDB with changed .graphml data?
Thanks again.
Frank
November 9th, 2013 at 7:19 pm
Hi,
I saw a very good example on this website for Building a Route Planner in Neo4j. I want to know where i wil get the complete project for this with librabry files? I want to use this example and in additionally i want improve it by building benchmark in it.
Thanks
regards,
Raj
November 9th, 2013 at 8:03 pm
Hi Rahul,
please have a look at “Tutorial Sources” – you may download the sources from my linked repository there. To build and run the examples all you need is a JDK and Maven.
Best regards
Micha
November 12th, 2013 at 2:51 pm
Hi Micha,
Thanks for your reply. I saw the tutorial sources you send me but i have not seen the building router and planning example in that. Can you please tell me where should i check ?
Thank You.
regards,
Rhaul
November 12th, 2013 at 7:50 pm
Hi, the following command runs the railroad example:
mvn exec:java -Dexec.mainClass=com.hascode.tutorial.RailroadExample