【问题标题】:Cypher query fails with variable length paths when trying to find all paths with unique node occurences尝试查找具有唯一节点出现的所有路径时,Cypher 查询因可变长度路径而失败
【发布时间】:2017-10-23 14:53:20
【问题描述】:

我有一个高度互连的图表,从特定节点开始 无论关系类型、方向或长度如何,我都想找到连接到它的所有节点。我想要做的是过滤掉包含超过 1 次节点的路径。但我得到的是一个

Neo.DatabaseError.General.UnknownError: key not found: UNNAMED27

我已经设法创建了一个更简单的数据库 在 neo4j 沙箱中并使用以下数据再次获得相同的消息:

CREATE (n1:Person { pid:1, name: 'User1'}), 
       (n2:Person { pid:2, name: 'User2'}),
       (n3:Person { pid:3, name: 'User3'}), 
       (n4:Person { pid:4, name: 'User4'}),
       (n5:Person { pid:5, name: 'User5'})

具有以下关系:

MATCH (n1{pid:1}),(n2{pid:2}),(n3{pid:3}),(n4{pid:4}),(n5{pid:5})
CREATE (n1)-[r1:RELATION]->(n2), 
       (n5)-[r2:RELATION]->(n2), 
       (n1)-[r3:RELATION]->(n3), 
       (n4)-[r4:RELATION]->(n3)

在上述模型中导致此问题的 Cypher 查询是

MATCH p= (n:Person{pid:1})-[*0..]-(m) 
WHERE ALL(c IN nodes(p) WHERE 1=size(filter(d in nodes(p) where c.pid = d.pid)) ) 
return  m

谁能看出这个查询有什么问题?

【问题讨论】:

  • 已测试 3.2.6 仍然出现此错误

标签: neo4j cypher


【解决方案1】:

这个错误对我来说似乎是一个错误。有一个closed neo4j issue 看起来很相似,但它应该在版本 3.2.1 中修复。您可能应该为它创建一个新问题,因为您的 cmets 声明您使用的是 3.2.5。

同时,这个查询应该得到你想要的结果:

MATCH p=(:Person{pid:1})-[*0..]-(m)
WITH m, NODES(p) AS ns
UNWIND ns AS n
WITH m, ns, COUNT(DISTINCT n) AS cns
WHERE SIZE(ns) = cns
return m

不过,您应该强烈考虑为可变长度路径搜索设置一个合理的上限。如果您不这样做,那么对于任何合理的 DB 大小,您的查询都可能需要 非常 很长时间和/或内存不足。

【讨论】:

  • 非常感谢您的出色回复。不幸的是,当我在我的实际数据库中尝试它时,这个查询永远不会结束。这可能是因为它属于循环,这是我想在我的小例子中使用 where 子句来避免的。您提供的查询也不能避免循环,但在这个小数据集中运行良好。你是对的,这似乎是较旧的 neo4j 问题,一旦我找到时间,我可能会要求它。
【解决方案2】:

在查找路径时,Cypher 永远不会在一条路径中访问同一个节点两次。所以MATCH (a:Start)-[*]-(b) RETURN DISTINCT b 将返回所有连接到 a 的节点。 (这里的 DISTINCT 是多余的,但它会影响查询性能。在您的 Neo4j 版本上使用 PROFILE 来查看它是否关心,哪个更好)

注意:这从 Neo4j 3.2 Cypher 规划器开始工作。对于以前的版本 在 Cypher 规划器中,执行此操作的唯一有效方法是使用 APOC,或者从起始节点向所有子节点添加 -[:connected_to]-> 关系,这样就不必探索路径。)

【讨论】:

  • 在我较大的数据库中,我尝试删除此 WHERE 子句。导致一个永无止境的查询。我限制了结果(最终得到答案)并看到它实际上两次访问了某些节点,从而陷入了循环。 Profile 也不起作用,因为它实际上尝试执行查询。解释只是导致看到这个 UNNAMED27 可能是指我无法再命名的未命名的 var 长度关系。
  • @iltzortz 您使用的是什么版本的 Neo4j?此外,您可以使用()-[*..5]-() 限制深度。
  • @iltzortz WHERE 子句实际上并没有帮助它的 MATCH 时间。在初始无过滤器快速搜索失败后应用过滤器,并且使用深度连接图,初始扫描可以锁定查询。
  • 版本 3.2.5 我知道我可以设置一个我不想设置的上限。
  • @Tezra:MATCH 子句可以多次返回相同的 node,但不会两次生成具有相同 relationship 的路径。
猜你喜欢
  • 2016-09-02
  • 1970-01-01
  • 2015-04-21
  • 2020-08-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多