Since Neo4j kernel version 1.1 there's a new traversal framework included. It's still considered experimental, and the team would be happy to receive feedback on it.
There's also information on the traversal framework on the wiki.
This is the node space we want to traverse into using the new traversal framework:
Here's how to get friends and friends of friends of a person in the network:
private static Traverser getFriends( final Node person ) { TraversalDescription td = Traversal.description().breadthFirst().relationships( RelTypes.KNOWS, Direction.OUTGOING ).filter( Traversal.returnAllButStartNode() ); return td.traverse( person ); }
How to perform the actual traversal and print the results:
Traverser friendsTraverser = getFriends( neoNode ); int numberOfFriends = 0; for ( Path friendPath : friendsTraverser ) { System.out.println( "At depth " + friendPath.length() + " => " + friendPath.endNode().getProperty( "name" ) ); numberOfFriends++; }
Let's find out who coded the Matrix:
private static Traverser findHackers( final Node startNode ) { TraversalDescription td = Traversal.description().breadthFirst().relationships( RelTypes.CODED_BY, Direction.OUTGOING ).relationships( RelTypes.KNOWS, Direction.OUTGOING ).filter( Traversal.returnWhereLastRelationshipTypeIs( RelTypes.CODED_BY ) ); return td.traverse( startNode ); }
Print out the result:
Traverser traverser = findHackers( getNeoNode() ); int numberOfHackers = 0; for ( Path hackerPath : traverser ) { System.out.println( "At depth " + hackerPath.length() + " => " + hackerPath.endNode().getProperty( "name" ) ); numberOfHackers++; }
Here we have users assigned to groups, and groups containing other groups. This is the full node space of our example:
Get the admins using the new traversal framework:
Node admins = getGroupByName( "Admins" ); TraversalDescription td = Traversal.description().breadthFirst().relationships( RoleRels.PART_OF, Direction.INCOMING ).relationships( RoleRels.MEMBER_OF, Direction.INCOMING ).filter( Traversal.returnAllButStartNode() ); for ( Path path : td.traverse( admins ) ) { Node part = path.endNode(); System.out.println( part.getProperty( NAME ) + " " + ( path.length() - 1 ) ); }
Get the admins using the old traversal framework:
Node admins = getGroupByName( "Admins" ); Traverser traverser = admins.traverse( Traverser.Order.BREADTH_FIRST, StopEvaluator.END_OF_GRAPH, ReturnableEvaluator.ALL_BUT_START_NODE, RoleRels.PART_OF, Direction.INCOMING, RoleRels.MEMBER_OF, Direction.INCOMING ); for ( Node part : traverser ) { System.out.println( part.getProperty( NAME ) + " " + ( traverser.currentPosition().depth() - 1 ) ); }
Get the group memberships of a user using the new traversal framework:
Node jale = getUserByName( "Jale" ); TraversalDescription td = Traversal.description().depthFirst().relationships( RoleRels.MEMBER_OF, Direction.OUTGOING ).relationships( RoleRels.PART_OF, Direction.OUTGOING ).filter( Traversal.returnAllButStartNode() ); for ( Path path : td.traverse( jale ) ) { Node membership = path.endNode(); System.out.println( membership.getProperty( NAME ) + " " + ( path.length() - 1 ) ); }
Get the group memberships of a user using the old traversal framework:
Node jale = getUserByName( "Jale" ); Traverser traverser = jale.traverse( Traverser.Order.DEPTH_FIRST, StopEvaluator.END_OF_GRAPH, ReturnableEvaluator.ALL_BUT_START_NODE, RoleRels.MEMBER_OF, Direction.OUTGOING, RoleRels.PART_OF, Direction.OUTGOING ); for ( Node membership : traverser ) { System.out.println( membership.getProperty( NAME ) + " " + ( traverser.currentPosition().depth() - 1 ) ); }
Get all groups using the new traversal framework:
Node referenceNode = graphDb.getReferenceNode(); TraversalDescription td = Traversal.description().breadthFirst().relationships( RoleRels.ROOT, Direction.INCOMING ).relationships( RoleRels.PART_OF, Direction.INCOMING ).filter( Traversal.returnAllButStartNode() ); for ( Node group : td.traverse( referenceNode ).nodes() ) { System.out.println( group.getProperty( NAME ) ); }
Get all groups using the old traversal framework:
Node referenceNode = graphDb.getReferenceNode(); Traverser traverser = referenceNode.traverse( Traverser.Order.BREADTH_FIRST, StopEvaluator.END_OF_GRAPH, ReturnableEvaluator.ALL_BUT_START_NODE, RoleRels.ROOT, Direction.INCOMING, RoleRels.PART_OF, Direction.INCOMING ); for ( Node group : traverser ) { System.out.println( group.getProperty( NAME ) ); }
Get all members of all groups using the new traversal framework:
Node referenceNode = graphDb.getReferenceNode(); TraversalDescription td = Traversal.description().breadthFirst().relationships( RoleRels.ROOT, Direction.INCOMING ).relationships( RoleRels.MEMBER_OF, Direction.INCOMING ).relationships( RoleRels.PART_OF, Direction.INCOMING ).filter( new Predicate<Path>() { public boolean accept( Path item ) { if ( item.length() == 0 ) { return false; } return item.lastRelationship().isType( RoleRels.MEMBER_OF ); } } ); for ( Node group : td.traverse( referenceNode ).nodes() ) { System.out.println( group.getProperty( NAME ) ); }
Get all members of all groups using the old traversal framework:
Node referenceNode = graphDb.getReferenceNode(); Traverser traverser = referenceNode.traverse( Traverser.Order.BREADTH_FIRST, StopEvaluator.END_OF_GRAPH, new ReturnableEvaluator() { public boolean isReturnableNode( TraversalPosition currentPos ) { if ( currentPos.isStartNode() ) { return false; } Relationship rel = currentPos.lastRelationshipTraversed(); return rel.isType( RoleRels.MEMBER_OF ); } }, RoleRels.ROOT, Direction.INCOMING, RoleRels.PART_OF, Direction.INCOMING, RoleRels.MEMBER_OF, Direction.INCOMING ); for ( Node group : traverser ) { System.out.println( group.getProperty( NAME ) ); }