关于neo4j:Cypher-无限的路径长度和大的路径长度查询挂起

Cypher - unlimited path length and large path length queries hang

我正在使用Neo4j Community 4.0.4。
我使用Python的官方Bolt驱动程序遇到了此问题,但在Neo4j浏览器(版本4.0.7)中也可以完全重现。

我现在有一个非常简单的图,由以下节点和关系类型组成:

1
2
(:Document)-[:contains]->(:Block)
(:Block)<-[:prev]-(:Block)-[:next]->(:Block)

目前我的整个测试数据库中只有75个节点-1个Document节点和74个Block节点。

运行以下Cypher语句会使CPU达到100%,并且内存利用率无限期增加,之后我必须终止该会话:

1
2
3
match (d:Doc{name: 'doc name'})
optional match (d)-[*]-(n)
return d,n

在某些时候我也遇到了Java堆大小错误。
仅当我在关系上设置严格的上限或指定方向时,它才能开始工作,例如:

1
optional match (d)-[*..5]->(n)

例如,这已经行不通了(答案要花很多时间,所以我必须取消会话):

1
optional match (d)-[*..5]-(n)

考虑到(a)我正在执行严格的局部图遍历,认为图数据库应该特别擅长,(b)与不同起始节点关联的群集未连接,并且(c)我的测试数据集很小,这怎么可能发生?

从这些症状看来,引擎在准备结果时似乎根本无法跟踪已访问过哪些节点和关系……还是我错过了什么?

更新:

Neo4j工作人员刚刚在Neo4j社区论坛上回答了这个问题:
https://community.neo4j.com/t/getting-paths-of-any-length-or-long-paths-does-not-work/18298

我错误地认为Cypher只会动态地从路径唯一性遍历切换到节点唯一性遍历,因为匹配之后的操作仅处理节点而不处理关系。
我的假设很差-不仅Cypher不会自动执行此操作,而且如果遍历路径中的所有节点,遍历核心Cypher的ATALL也无法删除路径。

建议使用基于APOC的解决方案:

1
2
3
match (d:Doc{name: 'doc name'})
CALL apoc.path.subgraphNodes(d, {}) YIELD node as n
return d, n

在我的情况下,我断开了子图的连接,每个子图都是成千上万个节点,并且相对密集。尝试删除(:Doc)节点及其连接的所有对象之前,这会在将新版本的子图重新加载到Neo4j中时出现:

1
disconnect delete d, n

我将"重新加载之前删除旧版本"这一任务视为许多人在用例中可能遇到的子图的常见操作...安装和管理其他库(例如APOC或Graph Data Science库)似乎对于这种简单的事情来说是一个过大的杀伤力...但这是为了使删除变得更有针对性。


MATCH子句避免两次遍历相同的关系,因此这不是问题。但是,它仍可以多次在同一2个节点之间移动(只要使用了不同的关系)。

主要要考虑的是可变长度关系模式具有指数(时间和内存)复杂性。如果要遍历的节点平均具有R个相关关系,则MATCH子句必须遍历大约R**P个长度为P的可能路径。 P得到的越高(尤其是没有上限),则得到的越差。但是高R也很痛苦。