简体   繁体   English

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

[英]Neo4j - Find nodes who never had any relationship with a different node

Assuming that I have an example with nodes and relationships like this: 假设我有一个带有这样的节点和关系的示例:

(:Node_A) -[:rel_a]-> (:Node_B) -[:rel_b]-> (:Node_C)

I want to find all the nodes of Node_A who never had relationship with a (:Node_C {label:'A'}) . 我想找到从未与(:Node_C {label:'A'})有关系的Node_A所有节点。

I tried: 我试过了:

MATCH (a:Node_A) -[:rel_a]-> (b:Node_B), (c:Node_C {label:'A'})
WHERE NOT (b) -[:rel_b]-> (c)
RETURN a

but I didn't get the expected result. 但是我没有得到预期的结果。

In case I have these nodes and relationships, I don't want node_a to be returned. 如果我具有这些节点和关系,则不希望返回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'})

How can I match nodes that never had any relationship with a (:Node_C {label:'A'}) ? 如何匹配从未与(:Node_C {label:'A'})没有任何关系的节点?

The reason you didn't get the expected result is because there IS a path matching the given pattern (a Node_A node connected to a Node_B node such that the Node_B node isn't connected to a Node_C node with label:'A' ). 之所以没有得到预期的结果,是因为存在与给定模式匹配的路径(一个Node_A节点连接到Node_B节点,因此Node_B节点未连接到label:'A'Node_C节点)。 This is because, according to the description of your example graph, you have 2 :Node_B nodes connected to your single :Node_A node. 这是因为,根据示例图的描述,您有2个:Node_B节点连接到您的单个:Node_A节点。 One of them is connected to two :Node_C nodes, one of which is the :Node_C node that you're trying to avoid (and in that case THAT path with that :Node_B node gets filtered out because of your WHERE clause), and the other :Node_B node is connected to the safe :Node_C node with the label 'C', and this is the path that fits your query and is returned. 其中一个连接到两个:Node_C节点,其中一个是您要避免的:Node_C节点(在这种情况下,由于您的WHERE子句,带有该:Node_B节点的THAT路径被过滤掉了),并且其他:Node_B节点连接到带有标签'C'的安全:Node_C节点,这是适合您的查询并返回的路径。

There are a few ways you can get the filtering you want. 您可以通过几种方式获得所需的过滤条件。

One is to define the full pattern you want excluded entirely into the WHERE clause, and leaving the :Node_B part out of the MATCH clause: 一种是在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

If you don't know or don't care about the intermediate nodes or relationships between a and c , you can omit them from the pattern: 如果您不了解或不关心中间节点或ac之间a关系,则可以从模式中省略它们:

MATCH (a:Node_A), (c:Node_C {label:'A'})
WHERE NOT (a) --> () --> (c)
RETURN a

You can express the same thing using variable-length relationships where we know c can only be 2 hops away: 您可以使用可变长度关系表示同一件事,其中我们知道c只能相距2跳:

MATCH (a:Node_A), (c:Node_C {label:'A'})
WHERE NOT (a) -[*2]-> (c)
RETURN a

EDIT 编辑

stdob-- correctly points out that for all these approaches, we've assumed that a :Node_C node with label:'A' exists in the graph. stdob--正确地指出,对于所有这些方法,我们假设图中存在带有label:'A':Node_C节点。 If this isn't guaranteed, and it so happens that there IS no such node, then these queries won't return anything back. 如果不能保证这一点,并且碰巧没有这样的节点,那么这些查询将不会返回任何内容。

If we have to cope with that potential case, then it's best to move this from the MATCH into the WHERE clause: 如果我们必须处理这种潜在的情况,那么最好将其从MATCH移到WHERE子句中:

MATCH (a:Node_A)
WHERE NOT (a) -[*2]-> (:Node_C {label:'A'})
RETURN a

In fact, that's probably a good thing to do in any case, as if we had multiple nodes like this instead of only one it could mess up our results if we kept this in the MATCH clause. 实际上,在任何情况下这都是一件好事,好像我们有多个这样的节点,而不是只有一个这样的节点,如果将其保留在MATCH子句中,可能会弄乱我们的结果。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM