【发布时间】:2020-08-23 01:40:30
【问题描述】:
我正在使用 Neo4j 社区 4.0.4。
我在使用 Python 的官方 Bolt 驱动程序时遇到过这个问题,但它在 Neo4j 浏览器(版本 4.0.7)中也完全可以重现。
我现在有一个非常简单的图表,由以下节点和关系类型组成:
(:Document)-[:contains]->(:Block)
(:Block)<-[:prev]-(:Block)-[:next]->(:Block)
目前我的整个测试数据库中只有 75 个节点 - 1 个 Document 节点和 74 个 Block 节点。
运行以下 Cypher 语句会使 CPU 达到 100%,并且内存利用率无限上升,之后我必须终止会话:
match (d:Doc{name: 'doc name'})
optional match (d)-[*]-(n)
return d,n
我在某些时候也遇到了 Java 堆大小错误。 只有当我对关系设置严格的上限或指定方向时,它才会开始工作,例如:
optional match (d)-[*..5]->(n)
例如,这已经不起作用(答案需要永远,所以我必须终止会话):
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 根本无法在遍历期间丢弃路径。
建议使用基于 APOC 的解决方案:
match (d:Doc{name: 'doc name'})
CALL apoc.path.subgraphNodes(d, {}) YIELD node as n
return d, n
在我的例子中,我已经断开了子图,每个子图都有数万个节点并且相对密集。在将新版本的子图重新加载到 Neo4j 之前,尝试删除 (:Doc) 节点及其连接的所有内容时会出现这种情况:
disconnect delete d, n
我认为“在重新加载之前删除旧版本”的任务是许多人在其用例中可能拥有的子图的一项非常常见的操作任务......安装和管理其他库(如APOC 或图形数据科学库)对于这么简单的事情似乎有点过头了......但要么就是这样,要么让删除更有针对性。
【问题讨论】: