The Matrix

Neo4j Wiki から

This is a small example that shows modeling of a social network.

Image:Matrix.png

The graph shows who KNOWS who, and who was CODED_BY whom. For convenient access to the most important node a ROOT relation from the reference node of the graph was added. As the names indicate, KNOWS is thought of as bidirectional and CODED_BY as a directed relationship. In Neo4j, all relationsips are directed, but it does not force these sematics on to the user. By using Direction.BOTH in traversals, the direction of relationships will be ignored.

At the bottom of the page there are links to the source code, if you want to know how the graph is created.

[edit] Find the friends

OK, now we want to know the friends of one person. And the friends of the friends too -- all of them. This is one way to implement it:

private void printFriends( Node person )
{
    Traverser traverser = person.traverse( 
        Order.BREADTH_FIRST,
        StopEvaluator.END_OF_GRAPH,
        ReturnableEvaluator.ALL_BUT_START_NODE,
        MyRelationshipTypes.KNOWS,
        Direction.OUTGOING );
    for ( Node friend : traverser )
    {
        System.out.println( friend.getProperty( "name" ) );
    }
}

In short, we set up a traverser to find the friends through following all KNOWS relationships. What the traverser needs to know is:

  • order: in which order to traverse
  • stop evaluator: when to stop
  • returnable evaluator: which nodes to return
  • relationship type: which relationship types to follow
  • direction: in what direction to follow relationships

So the traverser does most of the work for us, we can easily iterate over it to get all of the friends.

This is how the output will look when we feed the function with the Thomas Andersson node:

Trinity
Morpheus
Cypher
Agent Smith

The full code example (see link in the reference section at the end of this page) will also print the depth or distance.

[edit] Find the hackers

How to find the hackers in the graph?The basic idea is the same in this case, but we need to set up the traverser in a different way, to recognize the type of every single relationship (That's where the ReturnableEvaluator stuff comes in to help us).

In this code snippet, we'll also check the traverser for the current depth. This will give us the shortest distance from the starting node to each hacker.

private void findHackers( Node startNode )
{
    Traverser traverser = startNode.traverse(
        Order.BREADTH_FIRST,
        StopEvaluator.END_OF_GRAPH,
        new ReturnableEvaluator()
        {
            public boolean isReturnableNode( TraversalPosition currentPosition )
            {
                Relationship rel = currentPosition.lastRelationshipTraversed();
                if ( rel != null && rel.isType( MyRelationshipTypes.CODED_BY ) )
                {
                    return true;
                }
                return false;
            }
        },
        MyRelationshipTypes.CODED_BY, Direction.OUTGOING,
        MyRelationshipTypes.KNOWS, Direction.OUTGOING );
    for ( Node hacker : traverser )
    {
        TraversalPosition position = traverser.currentPosition();
        System.out.println( "At depth " + position.depth() + " => "
            + hacker.getProperty( "name" ) );
    }
}

This is what the output will look like:

At depth 4 => The Architect


[edit] References

Neo4j のサイト
ツールボックス