假设我有一个这样的节点和关系的例子:
(:Node_A) -[:rel_a]-> (:Node_B) -[:rel_b]-> (:Node_C)
我想找到 Node_A
中从未与 (:Node_C {label:'A'})
建立关系的所有节点。
我试过:
MATCH (a:Node_A) -[:rel_a]-> (b:Node_B), (c:Node_C {label:'A'})
WHERE NOT (b) -[:rel_b]-> (c)
RETURN a
但我没有得到预期的结果。
如果我有这些节点和关系,我不想返回 node_a
。
(node_a:Node_A) -[:rel_a]-> (b1:Node_B),
(node_a:Node_A) -[:rel_a]-> (b2:Node_B),
(b1:Node_B) -[:rel_b]-> (c:Node_C {label:'A'}),
(b1:Node_B) -[:rel_b]-> (c1:Node_C {label:'B'}),
(b2:Node_B) -[:rel_b]-> (c2:Node_C {label:'C'})
如何匹配从未与 (:Node_C {label:'A'})
有任何关系的节点?
最佳答案
你没有得到预期结果的原因是因为存在匹配给定模式的路径(Node_A
节点连接到 Node_B
节点,这样 Node_B
节点未连接到具有 label:'A'
的 Node_C
节点)。这是因为,根据示例图的描述,您有 2 个 :Node_B 节点连接到您的单个 :Node_A 节点。其中一个连接到两个 :Node_C 节点,其中一个是您试图避免的 :Node_C 节点(在这种情况下,由于您的 WHERE 子句,带有该 :Node_B 节点的路径被过滤掉),并且其他 :Node_B 节点连接到带有标签“C”的安全 :Node_C 节点,这是适合您的查询并返回的路径。
您可以通过多种方式获得所需的过滤。
一种是将您想要完全排除的完整模式定义到 WHERE 子句中,并将 :Node_B 部分留在 MATCH 子句之外:
MATCH (a:Node_A), (c:Node_C {label:'A'})
WHERE NOT (a) -[:rel_a]-> (:Node_B) -[:rel_b]-> (c)
RETURN a
如果您不知道或不关心a
和c
之间的中间节点或关系,您可以从模式中省略它们:
MATCH (a:Node_A), (c:Node_C {label:'A'})
WHERE NOT (a) --> () --> (c)
RETURN a
您可以使用我们知道 c
只能是 2 跳的可变长度关系来表达同样的事情:
MATCH (a:Node_A), (c:Node_C {label:'A'})
WHERE NOT (a) -[*2]-> (c)
RETURN a
编辑
stdob-- 正确地指出,对于所有这些方法,我们假设图中存在一个带有 label:'A'
的 :Node_C
节点。如果不能保证这一点,并且碰巧没有这样的节点,那么这些查询将不会返回任何内容。
如果我们必须处理这种潜在情况,那么最好将它从 MATCH 移到 WHERE 子句中:
MATCH (a:Node_A)
WHERE NOT (a) -[*2]-> (:Node_C {label:'A'})
RETURN a
事实上,这在任何情况下都可能是一件好事,因为如果我们有多个这样的节点而不是只有一个节点,如果我们将其保留在 MATCH 子句中,它可能会弄乱我们的结果。
关于database - Neo4j - 查找从未与其他节点有任何关系的节点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51059658/