Neo4j - 查找从未与其他节点有任何关系的节点
Neo4j - Find nodes who never had any relationship with a different node
假设我有一个这样的节点和关系示例:
(:Node_A) -[:rel_a]-> (:Node_B) -[:rel_b]-> (:Node_C)
我想找到从未与 (:Node_C {label:'A'})
有关系的 Node_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'})
有任何关系的节点?[=17=]
你没有得到预期结果的原因是因为有一条路径匹配给定的模式(Node_A
节点连接到 Node_B
节点使得 Node_B
节点未连接到具有 label:'A'
的 Node_C
节点)。这是因为,根据您的示例图的描述,您有 2 个 :Node_B 节点连接到您的单个 :Node_A 节点。其中之一连接到两个 :Node_C 节点,其中一个是您要避免的 :Node_C 节点(在这种情况下,该路径与该 :Node_B 节点由于您的 WHERE 子句而被过滤掉),另一个 :Node_B 节点连接到带有标签 'C' 的安全 :Node_C 节点,这是适合您的查询的路径并且 returned.
您可以通过多种方式获得所需的过滤。
一种是将要完全排除的完整模式定义到 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
节点。如果不能保证这一点,并且碰巧没有这样的节点,那么这些查询将不会 return 返回任何内容。
如果我们必须处理这种潜在情况,那么最好将其从 MATCH 移到 WHERE 子句中:
MATCH (a:Node_A)
WHERE NOT (a) -[*2]-> (:Node_C {label:'A'})
RETURN a
事实上,这在任何情况下都可能是一件好事,因为如果我们有多个这样的节点而不是只有一个节点,如果我们将其保留在 MATCH 子句中,它可能会弄乱我们的结果。
假设我有一个这样的节点和关系示例:
(:Node_A) -[:rel_a]-> (:Node_B) -[:rel_b]-> (:Node_C)
我想找到从未与 (:Node_C {label:'A'})
有关系的 Node_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'})
有任何关系的节点?[=17=]
你没有得到预期结果的原因是因为有一条路径匹配给定的模式(Node_A
节点连接到 Node_B
节点使得 Node_B
节点未连接到具有 label:'A'
的 Node_C
节点)。这是因为,根据您的示例图的描述,您有 2 个 :Node_B 节点连接到您的单个 :Node_A 节点。其中之一连接到两个 :Node_C 节点,其中一个是您要避免的 :Node_C 节点(在这种情况下,该路径与该 :Node_B 节点由于您的 WHERE 子句而被过滤掉),另一个 :Node_B 节点连接到带有标签 'C' 的安全 :Node_C 节点,这是适合您的查询的路径并且 returned.
您可以通过多种方式获得所需的过滤。
一种是将要完全排除的完整模式定义到 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
节点。如果不能保证这一点,并且碰巧没有这样的节点,那么这些查询将不会 return 返回任何内容。
如果我们必须处理这种潜在情况,那么最好将其从 MATCH 移到 WHERE 子句中:
MATCH (a:Node_A)
WHERE NOT (a) -[*2]-> (:Node_C {label:'A'})
RETURN a
事实上,这在任何情况下都可能是一件好事,因为如果我们有多个这样的节点而不是只有一个节点,如果我们将其保留在 MATCH 子句中,它可能会弄乱我们的结果。