Skip to content

Traversals

jadell edited this page Oct 7, 2013 · 4 revisions

Traversals are one of the more powerful ways of pulling data out of a graph database. neo4jphp provides full access to the Neo4j REST API's traversal methods.

If phrases like "prune evaluator" and "return filter" are meaningless to you in the context of traversals, start here: http://docs.neo4j.org/chunked/milestone/rest-api-traverse.html

Basic Traversal

The easiest way to create and execute a traversal is using Neo4j's built-in prune evaluators and return filters. The following traversal finds every node within 4 outgoing "KNOWS" relationships of the starting node, including the starting node.

$traversal = new Everyman\Neo4j\Traversal($client);
$traversal->addRelationship('KNOWS', Relationship::DirectionOut)
    ->setPruneEvaluator(Traversal::PruneNone)
    ->setReturnFilter(Traversal::ReturnAll)
    ->setMaxDepth(4);

$nodes = $traversal->getResults($startNode, Traversal::ReturnTypeNode);

To exclude the starting node from the list of returned nodes, set the return filter to Traversal::ReturnAllButStart. It is important to set a maximum depth to traverse using Traversal::setMaxDepth() because the default depth is 1.

It is possible to set other parameters of the traversal, including the order (depth-first or breadth-first), how uniqueness should be determined, and whether to return nodes, relationships or paths.

Custom Prune Evaluator and Return Filter

neo4jphp allows you to specify your own custom function for the prune evaluator and return filter. These functions are written in Javascript, and passed through to the server for evaluation.

This snippet prunes any path that contains a node with a "name" property that contains the letter "t", and returns only paths more than 3 relationships long:

$traversal = new Everyman\Neo4j\Traversal($client);
$traversal->setMaxDepth(10)
    ->setPruneEvaluator('javascript', "position.endNode().getProperty('name').toLowerCase().contains('t')")
    ->setReturnFilter('javascript', "position.length() > 3");

$paths = $traversal->getResults($startNode, Traversal::ReturnTypePath);

Paged Traversal

If a traversal is expected to return a large number of results, it can be paged, much like SQL's "LIMIT" and "OFFSET" keywords.

Using the traversal from above, this snippet will retrieve 10 results at a time:

$pager = new Everyman\Neo4j\Pager($traversal, $startNode, Traversal::ReturnTypeNode);
$pager->setPageSize(10)
    ->setLeaseTime(120);

while ($results = $pager->getNextResults()) {
    foreach ($results as $node) {
        echo $node->getProperty('name');
    }
}

Because of the way the REST server works, traversals will "time out" and not return any more pages after a default of 60 seconds. The call to Pager::setLeaseTime() above tells the server to hold on to the traversal and continue returning pages for up to 2 minutes (120 seconds.)

Pager::getNextResults() will return null when there are no more results of the traversal, or the traversal times out. Note that it is only possible to retrieve the next page of a traversal. You cannot retrieve a previously returned page.

Clone this wiki locally