Neo4j 遍历 API 与 Cypher

Neo4j Traversal API vs. Cypher

我什么时候应该选择 Neo4j 的遍历框架而不是 Cypher?

例如,对于朋友的朋友查询,我将编写一个 Cypher 查询,如下所示:

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

并且相应的遍历实现需要对 friends_at_depth_1friends_at_depth_2 进行两次遍历(或核心 API 调用以获取关系)并使用以下方法找到这两个集合的差异普通 java 构造,在遍历描述之外。如果我在这里错了,请纠正我。

有什么想法吗?

关于 Cypher 与遍历 API 要记住的关键是遍历 API 是访问图的命令式方式,而 Cypher 是访问图的声明式方式。 You can read more about that difference here 但简而言之,在命令式访问中,您要准确地告诉数据库如何 获取图表。 (例如,我想进行深度优先搜索,p运行e 这些分支,当我遇到某些节点时停止,等等)。在声明式图形查询中,您要指定 您想要的内容,并将如何获得它的所有方面委托给 Cypher 实现。

在你的查询中,我会稍微修改一下:

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

(我添加确保 p<>fof 因为朋友链接可能会回到原来的人)

要在遍历器中执行此操作,您不需要两个遍历器,只需一个。您将仅遍历 FRIEND 个关系,在深度 2 处停止,并累积一组结果。

现在,我将尝试证明您几乎应该始终使用 Cypher,并且永远不要使用遍历 API,除非您有非常特殊的情况。以下是我的理由:

  1. 声明式查询非常强大,因为它使您无需考虑如何查询。您只需要知道您想要什么。这意味着您可以将更多的时间花在代码应该做什么上,而花更少的时间在实现细节上。
  2. cypher 查询执行器一直在变得更好(2.2 版将有一个基于成本的计划器),当然他们付出了很多努力来确保 cypher 利用所有可用的索引。对于许多查询,cypher 不可能比遍历更好地查找数据,除非你在编写遍历时非常小心。
  3. Cypher 比编写自己的遍历代码少得多,后者经常需要您实现某些 类 来执行专门的停止条件等。
  4. 目前,cypher可以运行在嵌入式数据库中,或者在服务器上。如果你想 运行 遍历,你不能将它远程发送到服务器来执行;也许充其量您可以编写一个服务器扩展来进行遍历。所以我觉得目前cypher比较灵活。

好的,什么时候应该使用遍历?我知道的两个关键案例(其他人可能会建议其他人)

  1. 有时您需要对遍历的所有内容执行复杂的自定义 java 代码操作。在这种情况下,您将遍历器用作某种 "visitor function",有时遍历比密码更方便使用,具体取决于 java 的性质,您是 运行在节点上 ning。
  2. 有时您的性能要求如此强烈,您需要手动遍历图形,因为图形结构的某些方面可以在遍历器中加以利用,使其运行得更快,而 Cypher 无法利用。这种情况确实发生了,但首先进行这通常不是一个好主意。

本书节选

Core API, Traversal Framework or Cypher?

核心 API 允许开发人员微调他们的查询,以便他们表现出高 与底层图形的亲和力。编写良好的核心 API 查询通常比 任何其他方法。缺点是这样的查询可能很冗长,需要相当多的 开发人员的努力。此外,它们与底层图形的高度亲和力 使它们与其结构紧密耦合。当图形结构发生变化时,它们 经常会坏。 Cypher 可以更容忍结构变化——比如 可变长度路径有助于减轻变化和变化。

The Traversal Framework is both more loosely coupled than the Core API (because it allows the developer to declare informational goals), and less verbose, and as a result a query written using the Traversal Framework typically requires less developer effort than the equivalent written using the Core API. Because it is a general-purpose framework, however, the Traversal Framework tends to perform marginally less well than a well-written Core API query.

If we find ourselves in the unusual situation of coding with the Core API or Traversal Framework (and thus eschewing Cypher and its affordances), it’s because we are working on an edge case where we need to finely craft an algorithm that cannot be expressed effectively using Cypher’s pattern matching. Choosing between the Core API and the Traversal Framework is a matter of deciding whether the higher abstraction/ lower coupling of the Traversal Framework is sufficient, or whether the close-tothe- metal/higher coupling of the Core API is in fact necessary for implementing an algorithm correctly and in accordance with our performance requirements.

参考:Graph Databases, New Opportunities for Connected Data,p161

什么是密码?

开发人员文档中的定义如下:cypher 是一种声明式的,受 SQL 启发的语言,用于使用 ascii-art 语法直观地描述图形中的模式。

您可以找到更多相关信息 here

什么是核心 API 实际上?

我发现 this page 有以下句子:

Besides an object-oriented API to the graph database, working with Node, Relationship, and Path objects, it also offers highly customizable, high-speed traversal- and graph-algorithm implementations.

所以实际上核心 API 处理基本对象,例如属于 org.neo4j.graphdb 包的 NodeRelationship

您可以在 its developer guide 找到更多信息。

什么是遍历 API 实际上?

遍历API在核心API中增加了更多的接口,方便我们进行遍历,而不是从头开始编写整个遍历逻辑。这些接口包含在 org.neo4j.graphdb.traversal 包中。

您可以在 its developer guide 找到更多信息。

三者的关系

根据this answer

The Traversal API is built on the Core API, and Cypher is build on the Traversal API; So anything you can do in Cypher, can be done with the other 2.

所有三个都完成了相同的示例

2012 年的

This 教程展示了所有三个都在执行相同的任务,其中核心 API 最快。它包括安德烈斯·泰勒的一句话:

Cypher is just over a year old. Since we are very constrained on developers, we have had to be very picky about what we work on the focus in this first phase has been to explore the language, and learn about how our users use the query language, and to expand the feature set to a reasonable level.
I believe that Cypher is our future API. I know you can very easily outperform Cypher by handwriting queries. like every language ever created, in the beginning you can always do better than the compiler by writing by hand but eventually, the compiler catches up

文章结论:

So far I was only using the Java Core API working with neo4j and I will continue to do so.
If you are in a high speed scenario (I believe every web application is one) you should really think about switching to the neo4j Java core API for writing your queries. It might not be as nice looking as Cypher or the traverser Framework but the gain in speed pays off.
Also I personally like the amount of control that you have when traversing over the core yourself.