假设我有一个带有这样的节点和关系的示例:
(: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'})
有任何关系的节点?
答案 0 :(得分:2)
之所以没有获得预期的结果,是因为存在与给定模式匹配的路径(一个Node_A
节点连接到一个Node_B
节点,使得Node_B
节点未通过Node_C
连接到label:'A'
节点)。这是因为,根据示例图的描述,您有2个:Node_B节点连接到您的单个:Node_A节点。其中一个连接到两个:Node_C节点,其中一个是您要避免的:Node_C节点(在这种情况下,由于您的WHERE子句,带有该:Node_B节点的THAT路径被过滤掉了),并且其他: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--正确地指出,对于所有这些方法,我们假设图中存在带有:Node_C
的{{1}}节点。如果不能保证这一点,并且碰巧没有这样的节点,那么这些查询将不会返回任何内容。
如果我们必须处理这种潜在的情况,那么最好将其从MATCH移到WHERE子句中:
label:'A'
实际上,在任何情况下这都是一件好事,好像我们有多个这样的节点而不是只有一个那样,如果将其保留在MATCH子句中,可能会弄乱我们的结果。