Neo4j-查找从未与其他节点有任何关系的节点

时间:2018-06-27 09:50:41

标签: database neo4j nosql cypher graph-databases

假设我有一个带有这样的节点和关系的示例:

(: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'})有任何关系的节点?

1 个答案:

答案 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

如果您不了解或不关心ac之间的中间节点或关系,则可以从模式中省略它们:

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子句中,可能会弄乱我们的结果。