麻烦使用OPTIONAL MATCH与MATCH和WHERE

时间:2017-08-25 21:36:15

标签: neo4j cypher

我有一个不符合预期的cypher查询,我试图找出原因。我怀疑我不完全理解OPTIONAL MATCH的工作原理。

数据库有一个(:'Person::Current')节点和一个(:'Trait::Current')节点。它没有(:'PersonTrait::Current')节点。

如果我运行此查询,则会正确返回{1}} 1

count(t)

MATCH (n:`Person::Current` {uuid: $person_id}), (t:`Trait::Current` {uuid: $trait_id}) WHERE NOT ( (n)-[:PERSON_TRAIT]->(:`PersonTrait::Current` {has: true})-[:PERSON_TRAIT]->(t) OR (n)-[:PERSON_TRAIT]->(:`PersonTrait::Current` {has: false})-[:PERSON_TRAIT]->(t) OR (t)-[:GIVES_TRAIT]->(:`GivesTrait::Current`)-[:GIVES_TRAIT]->(:`Trait::Current`)<-[:PERSON_TRAIT]-(:`PersonTrait::Current` {has: false})<-[:PERSON_TRAIT]-(n) ) RETURN count(t) as res 节点以

的形式添加到数据库中
(:'PersonTrait::Current')

我的查询正确返回计数(t)为0。

但是,如果我尝试使用(:`Person::Current`)-[:PERSON_TRAIT]->(:`PersonTrait::Current` {has: true})-[:PERSON_TRAIT]->(:`Trait::Current`) 来干扰查询,就像这样

OPTIONAL MATCH

MATCH (n:`Person::Current` {uuid: $person_id}), (t:`Trait::Current` {uuid: $trait_id}) OPTIONAL MATCH (pt:`PersonTrait::Current`) WHERE NOT ( ((n)-[:PERSON_TRAIT]->(pt)-[:PERSON_TRAIT]->(t) AND exists(pt.has)) OR (t)-[:GIVES_TRAIT]->(:`GivesTrait::Current`)-[:GIVES_TRAIT]->(:`Trait::Current`)<-[:PERSON_TRAIT]-(pt {has: false})<-[:PERSON_TRAIT]-(n) ) RETURN count(t) as res 节点以

的形式添加到数据库时,查询错误地返回count(t)1
(:'PersonTrait::Current')

任何人都知道出了什么问题?如果(:`Person::Current`)-[:PERSON_TRAIT]->(:`PersonTrait::Current` {has: true})-[:PERSON_TRAIT]->(:`Trait::Current`) 节点存在适当的模式,WHERE NOT子句应该过滤掉(t)个节点。

感谢!!!

1 个答案:

答案 0 :(得分:1)

我认为问题在于理解WHERE子句,因为WHERE仅适用于前一个MATCH,OPTIONAL MATCH或WITH子句。

在这种情况下,它与OPTIONAL MATCH配对,因此当WHERE为false时,行将不会被过滤掉,它的行为与OPTIONAL MATCH失败时的行为相同,因此新引入的变量在OPTIONAL MATCH中将被设置为null。

如果希望WHERE过滤掉行,请将其与WITH子句配对:

MATCH (n:`Person::Current` {uuid: $person_id}), (t:`Trait::Current` {uuid: $trait_id})
OPTIONAL MATCH (pt:`PersonTrait::Current`)
WITH n, t, pt
WHERE NOT (
  ((n)-[:PERSON_TRAIT]->(pt)-[:PERSON_TRAIT]->(t) AND exists(pt.has)) OR
  (t)-[:GIVES_TRAIT]->(:`GivesTrait::Current`)-[:GIVES_TRAIT]->(:`Trait::Current`)<-[:PERSON_TRAIT]-(pt {has: false})<-[:PERSON_TRAIT]-(n)
)
RETURN count(t) as res