NEO4J:查找断开的节点

4

我有这个样本数据

样本数据

使用这个样本查询

CREATE (a1:A {title: "a1"})
CREATE (a2:A {title: "a2"})
CREATE (a3:A {title: "a3"})

CREATE (b1:B {title: "b1"})
CREATE (b2:B {title: "b2"})

MATCH (a:A {title: "a1"}), (b:B {title: "b1"})
CREATE (a)-[r:LINKS]->(b)

MATCH (a:A), (b:B) return a,b

我希望实现的目标:

  1. 找到所有未连接到B节点类型的A节点类型(答案:a2、a3)
  2. 找到所有未连接到A节点类型的B节点类型(答案:b2)
  3. 这两个要求都是双向的,并且具有相同的查询模板。

我的进展情况

获取所有未连接到B节点的A节点:如预期获得a2和a3。

MATCH path=(a:A)-[r]-(b:B)
WHERE (a)-[r]-(b)
WITH collect(a) as al
MATCH (c:A)
WHERE not c IN al
RETURN c

获取所有已断开的B,我得到了b1和b2,这是不正确的,并且打印“al”表明该列表为空。

MATCH path=(b:B)-[r]-(a:A)
WHERE (b)-[r]-(a)
WITH collect(b) as al
MATCH (c:B)
WHERE not c IN al
RETURN c

一些方法。
WHERE (b)-[r]-(a) **!=** WHERE (a)-[r]-(b)

即使我将方向设置为双向(未提及),也无法正常工作。如果我在第二个查询中将其更改为WHERE (a)-[r]-(b),则可以正常工作,但我想要一个通用的双向查询。

1
为什么不简单地使用MATCH (a:A) WHERE NOT (a)--(:B) RETURN aMATCH (b:B) WHERE NOT (b)--(:A) RETURN b呢? - Bruno Peres
是的,它有效,谢谢。我确实理解这个简单的查询,但只是为了理解,你有任何想法,我的查询中哪一部分不正确?为什么我的where子句不能双向工作? - Srinath Ganesh
1个回答

4

使用 where 中的路径模式:

MATCH (a:A) WHERE NOT (a)-[:LINKS]-(:B)
RETURN a;

MATCH (b:B) WHERE NOT (b)-[:LINKS]-(:A)
RETURN b;

或者将它们合并为一个查询:

OPTIONAL MATCH (a:A) WHERE NOT (a)-[:LINKS]-(:B)
WITH collect(a) AS aNodes
OPTIONAL MATCH (b:B) WHERE NOT (b)-[:LINKS]-(:A)
WITH aNodes, 
     collect(b) AS bNodes
RETURN aNodes, bNodes

更新:为什么原始查询会产生错误的结果?

我认为这是一个bug。问题在于,当你在where中使用变量表示关系时,即使没有指定方向,模式也会隐式地从左到右使用:

// Will return 0, but for test data should return 1
MATCH (b:B)-[r]-(a:A) WHERE (b)-[r]-(a)
RETURN COUNT(*);

// Will return 1
MATCH (b:B)-[r]-(a:A) WHERE (b)<-[r]-(a)
RETURN COUNT(*);

// Will return 1
MATCH (b:B)-[r]-(a:A) WHERE (b)--(a)
RETURN COUNT(*);

// Will return 1
MATCH (b:B)-[r]-(a:A) WHERE (a)-[r]-(b)
RETURN COUNT(*);

1
@SrinathGanesh 非常有趣。我认为这是一个错误。已更新答案。 - stdob--
我还开始了一个新的讨论,专门针对您在查询中发现的异常。https://dev59.com/86rka4cB1Zd3GeqPf5fx - Srinath Ganesh
@SrinathGanesh MATCH (a:A), (b:B) WHERE NOT (a)--(b) RETURN a 匹配了一个未直接连接的 A-B 对。MATCH (a:A) WHERE NOT (a)--(:B) RETURN a 匹配了一个未连接到任何 B 的 A。它们在查找内容上完全不同,这就是结果不同的原因。此外,如果您只是将两个单独查询的结果合并,可以使用 UNION 将两个查询的结果组合成一个,而且它们之间没有干扰。 - Tezra
@SrinathGanesh 另一种看待它的方式是,Match 给你一组行(在第一个查询中,是 A 和 B 的笛卡尔积;第二个查询中只是 A 的列表)。然后 WHERE 部分仅过滤这些行(第一个查询中,过滤掉 A 和 B 没有直接连接的行;第二个查询中,过滤掉 A 与 B 有连接的行)。在第一个查询中,通过匹配 B,您将筛选逻辑绑定到每行的一个 B 实例。 - Tezra
1
NEO4J已经确认这是一个错误,并将在3.1中修复它。https://github.com/neo4j/neo4j/issues/11542 - Srinath Ganesh
显示剩余5条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接