使用WHERE排除节点不起作用

时间:2018-12-13 17:21:54

标签: neo4j cypher

当我尝试使用MATCH&WHERE排除节点时出现错误

我有下一个节点和关系:

MERGE (a1:accz {id: 1}) 
MERGE (a2:accz {id: 2}) 
MERGE (a3:accz {id: 3}) 
MERGE (a4:accz {id: 4}) 
MERGE (a5:accz {id: 5}) 
MERGE (i1:itemz {id: 1}) 
MERGE (i2:itemz {id: 2}) 
MERGE (i3:itemz {id: 3}) 
MERGE (i4:itemz {id: 4}) 
MERGE (a1)-[:AUTHOR]->(i1) 
MERGE (a2)-[:AUTHOR]->(i2) 
MERGE (a3)-[:AUTHOR]->(i1) 
MERGE (a3)-[:AUTHOR]->(i3) 
MERGE (a4)-[:AUTHOR]->(i4) 
MERGE (a4)-[:AUTHOR]->(i5) 
MERGE (a4)-[:AUTHOR]->(i5) 
MERGE (a5)-[:AUTHOR]->(i2) 
MERGE (a5)-[:AUTHOR]->(i5)

当我执行时(我以明确的方式包括了accz需要与之相关的项目):

MATCH (a:accz)-[:AUTHOR]->(i:itemz) WHERE ({id: i.id} IN [({id: 3}), ({id: 4})]) RETURN a

我得到了 accz 节点(3,4,5),并且还可以。但是然后我使用WHERE排除了一些节点,例如下一个查询:

MATCH (a:accz)-[:AUTHOR]->(i:itemz) WHERE ({id: i.id} IN [({id: 3}), ({id: 4})]) AND (NOT (a)-[:AUTHOR]->(:itemz {id:5})) RETURN a

但是我继续获取 accz 节点ID:5,这应该排除在外,因为acc {id:5}是(:itemz {id:5})的作者

我做错了什么?

1 个答案:

答案 0 :(得分:1)

在您的示例中看到的奇怪行为看起来像是错误,但可以加以解释(经过仔细考虑)。归根结底,一个结论是您应该避免在MERGE子句中使用未绑定的节点

奇怪的行为

您的创建查询没有MERGE子句来创建itemz节点i5。也就是说,缺少此子句:MERGE (i5:itemz {id: 5})

  1. 因此,似乎2个MERGE (a4)-[:AUTHOR]->(i5)子句应导致创建一个新的未标记的i5节点,该节点没有属性-但不会创建此类节点!

  2. 似乎MERGE (a5)-[:AUTHOR]->(i5)子句应该与新的i5建立关系-但相反,它意外地导致与i4形成关系!< / p>

说明

此代码段会导致奇怪的行为(我已经添加了注释以澄清):

MERGE (a4)-[:AUTHOR]->(i4) // Makes sure `(a4)-[:AUTHOR]->(i4)` relationship exists
MERGE (a4)-[:AUTHOR]->(i5) // Matches above relationship, so creates `i5` and binds it to `i4`!
MERGE (a4)-[:AUTHOR]->(i5) // Matches same relationship, so nothing is done.

因此,在执行代码段之后,i4i5被绑定到同一节点。这解释了奇怪的行为。

结论

为避免意外结果,应避免在MERGE子句中使用未绑定的节点。

如果在创建关系之前,您的创建查询已经包含MERGE (i5:itemz {id: 5})子句,则您的查询应该可以正常工作。第一个查询的结果将包含accz节点3和4,第二个查询的结果将仅包含3。

顺便说一下,({id: i.id} IN [({id: 3}), ({id: 4})])可以大大简化为i.id IN [3, 4]