Neo4j Traversal API vs. Cypher

cypher, neo4j

Solution

The key thing to remember about Cypher vs. the traversal API is that the traversal API is an imperative way of accessing a graph, and Cypher is a declarative way of accessing a graph. You can read more about that difference here but the short version is that in imperative access, you're telling the database exactly how to go get the graph. (E.g. I want to do a depth first search, prune these branches, stop when I hit certain nodes, etc). In declarative graph query, you're instead specifying what you want, and you're delegating all aspects of how to get it to the Cypher implementation.

In your query, I'd slightly revise it:

MATCH (p:Person {pid:'56'})-[:FRIEND*2..2]->(fof) 
WHERE NOT (p)-[:FRIEND]->(fof) AND
      p <> fof
RETURN fof.pid

(I added making sure that `p<>fof` because friend links might go back to the original person)

To do this in a traverser, you wouldn't need to have two traverser, just one. You'd traverse only `FRIEND` relationships, stop at depth 2, and accumulate a set of results.

Now, I'm going to attempt to argue that you should almost always use Cypher, and never use the traversal API unless you have very specific circumstances. Here are my reasons:

- Declarative query is very powerful, in that it frees you from thinking about the how. All you need to know is what you want. This means you spend more time focusing on what your code is supposed to do, and less time in implementation detail.

- The cypher query executor is getting better all the time (version 2.2 will have a cost based planner) and of course they put a lot of effort into making sure cypher exploits all available indexes. I'ts possible that for many queries, cypher would do a better job of finding your data than your traversal, unless you were very careful in coding the traversal.

- Cypher is just way less code than writing your own traversal, which will frequently require you to implement certain classes to do specialized stop conditions, etc.

- At present, cypher can run in embedded databases, or on the server. If you want to run a traversal, you can't send that remotely to a server to be executed; maybe at best you could write a server extension that did the traversal. So I think cypher is more flexible at present.

OK so when should you use traversal? Two key cases that I know of (others may suggest others)

- Sometimes you need to execute a complex custom java code operation on everything you traverse. In this case, you're using the traverser as a "visitor function" of sorts, and sometimes traversals are more convenient to use than cypher, depending on the nature of the java you're running on the nodes.

- Sometimes your performance requirements are so intense, you need to hand-traverse the graph, because there's some aspect of graph structure that you can exploit in the traverser to make it go faster that Cypher can't take advantage of. This does happen, but going to this first usually isn't a good idea.

Problem

When should I choose Neo4j’s traversal framework over Cypher? For example, for a friend-of-a-friend query I would write a Cypher query as follows: ``` MATCH (p:Person {pid:'56'})-[:FRIEND*2..2]->(fof) WHERE NOT (p)-[:FRIEND]->(fof) RETURN fof.pid ``` And the corresponding Traversal implementation would require two traversals for `friends_at_depth_1` and `friends_at_depth_2` (or a core API call to get the relationships) and find the difference of these two sets using plain java constructs, outside of the traversal description. Correct me if I’m wrong here. Any thoughts?

Original source