如果在Neo4j中至少有一个节点(相关但可能不是结果)具有某个属性,则返回结果

时间:2016-09-02 22:58:38

标签: neo4j cypher

我有一个由一组不相交的家谱组成的图表。

我有一个有一些OPTIONAL MATCH语句的工作查询,它​​允许我只获取main_person家谱中某人的直接父母和兄弟姐妹,假设这些亲属是对我们感兴趣:

MATCH (p:Person {main_person: 'y'})
OPTIONAL MATCH (p)<-[]-(parent:Person)
  WHERE parent.`person_of_interest` = 'y'
OPTIONAL MATCH (parent:Person)-[]->(sib:Person)
  WHERE sib <> p
  AND sib.`person_of_interest` = 'y'
RETURN
  p, parent, sib;  

但是说我想通过确定来确定这一点:

  • 至少有一个家庭成员拥有test_me = 'y'财产。这可能是一个遥远的家庭成员。它绝对不一定是person_of_interest的家庭成员,或者是一个亲密的家庭成员。

如果其中至少有一个人拥有此属性,那么我们可以返回我们正在寻找的家庭成员。但如果没有人拥有该财产,那么我们不希望该家族有任何结果。

我不确定如何构建它。我一直尝试从test_me = 'y'部分开始,并使用WITH

进行部署
 MATCH (p:Person)-[]-(m)
 WHERE ANY m.test_me = 'y'
 WITH p, m 
 . . .  

也许它应该更像:

MATCH (p:Person {main_person: 'y'})
OPTIONAL MATCH (p)<-[]-(parent:Person)
OPTIONAL MATCH (parent:Person)-[]->(sib:Person)
WHERE sib <> p
HAVING <condition here>
RETURN
p, parent, sib; 

如果这是SQL,我会尝试使用临时表来管理事物。

它们都没有真正起作用。

感谢您阅读本文。

2 个答案:

答案 0 :(得分:2)

[更新以回答更新的问题]

此查询可能适合您(或者可能内存不足或似乎永远无法运行):

MATCH (p:Person {main_person: 'y'})
  WHERE EXISTS((p)-[*0..]-({test_me: 'y'}))
OPTIONAL MATCH (p)<--(parent:Person)
  WHERE parent.person_of_interest = 'y'
OPTIONAL MATCH (parent:Person)-->(sib:Person)
  WHERE sib <> p AND sib.person_of_interest = 'y'
RETURN p, COLLECT(parent) AS parents, COLLECT(sib) AS sibs;

[*0..]语法表示可变长度关系搜索,其中匹配路径可以具有0个或更多个关系。查询使用0的下限而不是1(默认值)的原因是:我们还想测试p本身是否具有所需的test_me属性值。

但是,可变长度关系搜索因使用大量内存或在没有指定上限时花费很长时间而臭名昭着,所以通常查询会指定合理的上限(例如, ,[*0..5])。

顺便说一下,你应该传递诸如&#39; y&#39;之类的值。作为parameters,而不是硬编码。

答案 1 :(得分:1)

你肯定是在正确的轨道上,我认为即使你没有意识到,你已经有了答案。

您的描述中的内容仅作为查询的开始,只需进行一些修改:

MATCH pattern=(p:Person{main_person: 'y'})-[*]-()
WHERE ANY (person IN nodes(pattern) WHERE person.test_me = 'y')
WITH p
...

通过变量关系,您可以考虑树中的每个人(如果图表中存在非家庭关系,您希望在您的关系中使用类型,以确保您只考虑单个家庭和#39; s tree),以及main_person。如果p系列中没有人拥有您想要的属性,则p将为null,并且使用p的任何后续匹配将不会产生任何结果。这应该允许您自由地指定查询的其余部分,并且只要所有匹配包括p,您就不应该为没有所需属性值的系列获得任何结果。

编辑修改了我的查询,ANY()子句没有正确写入。