NEO4J:父子类型过滤,它们共享相同的标签

时间:2015-05-25 02:35:10

标签: neo4j cypher

我正在尝试找出如何返回包含以下内容的结果集:

  • 父/子类型节点,子节点与父节点具有相同的标签,因此是主结果中的有效项目
  • 但是,如果将Child节点作为" child"匹配
  • 如果父母不包含儿童
  • ,则应将其排除在主要结果之外

我可以把这个用于大部分工作,但我无法让第三点得到满意的效果。

我的查询类似于以下内容(已删除不相关的过滤):

MATCH (f:Fruit),(tof:TypeOfFruit)
WITH f, tof
MATCH (f)-[:IS_BANANA|IS_APPLE]->(tof)
WHERE NOT (tof)<-[:IS_APPLE]-(f)<-[:IN_FRUIT_SALAD]-()
OPTIONAL MATCH (tof)<-[:IS_BANANA]-(f)-[r:IN_FRUIT_SALAD]->(f1:Fruit)-[:IS_APPLE]->(tof)
WITH DISTINCT f, COLLECT(DISTINCT f1) AS f1
RETURN { fruit : f, fruitSaladComponents : f1 }  

所以我想回来:

  • 香蕉是苹果的水果沙拉的一部分
  • 不属于香蕉水果沙拉的苹果
  • &#34;孩子&#34;用香蕉制作水果沙拉的苹果

但是由于可选的匹配,这个查询返回的香蕉并不是苹果水果沙拉的一部分。

我认为有可能采用集合FILTER来实现此目的,但我还没有能够使其发挥作用。

我已尝试以UNION(并使用MATCH代替OPTIONAL MATCH)执行此操作,这可能会给我提供最接近我之后的结果,但由于UNION中的每个查询都是原子的,我最终不得不重复其他查询中的逻辑,我认为必须有一种方法可以在没有UNION的情况下执行此操作。

我对Cypher解决方案而不是建模解决方案非常感兴趣,但很高兴听到任何想法。

链接到NEO4J控制台:http://console.neo4j.org/?id=x03foa

在那里,您会看到UNION查询,该查询返回我之后的结果,但如果可能的话,我不想使用UNION,因为是我需要根据UNION的第一部分的结果进行过滤的条件加上我不想每次添加新的UNION时添加新的水果和香蕉不会永远是父母&#34; ...等等 -

MATCH (f:Fruit),(tof:TypeOfFruit)
WITH f, tof
MATCH (tof)<-[:IS_BANANA]-(f)-[:IN_FRUIT_SALAD]->(f1:Fruit)-[:IS_APPLE]->(tof)
WITH DISTINCT f, COLLECT(DISTINCT f1) AS f1
RETURN { fruit : f, fruitSaladComponents : f1 }
UNION
MATCH (f:Fruit),(tof:TypeOfFruit)
WITH f, tof
MATCH (f)-[:IS_APPLE]->(tof)
WHERE NOT (f)<-[:IN_FRUIT_SALAD]-()
WITH DISTINCT f,[] AS f1
RETURN { fruit : f, fruitSaladComponents : f1 }

更新2015年5月26日:

以下查询有效,但有没有更好的方法 - 即WHERE及后续OPTIONAL MATCH没有重复?

MATCH (f:Fruit),(tof:TypeOfFruit)
WITH f, tof
MATCH (f)-[:IS_BANANA|IS_APPLE]->(tof)
WHERE ((tof)<-[:IS_BANANA]-(f)-[:IN_FRUIT_SALAD]->(:Fruit)-[:IS_APPLE]->(tof)) OR ((tof)<-[:IS_APPLE]-(f) AND NOT (f)<-[:IN_FRUIT_SALAD]-())
OPTIONAL MATCH (tof)<-[:IS_BANANA]-(f)-[r:IN_FRUIT_SALAD]->(f1:Fruit)-[:IS_APPLE]->(tof)
WITH DISTINCT f, COLLECT(DISTINCT f1) AS f1
RETURN { fruit : f, fruitSaladComponents : f1 }

1 个答案:

答案 0 :(得分:0)

解决方案如上(移动WHERE子句略有变化) -

MATCH (f:Fruit),(tof:TypeOfFruit)
WITH f, tof
MATCH (f)-[:IS_BANANA|IS_APPLE]->(tof)
OPTIONAL MATCH (tof)<-[:IS_BANANA]-(f)-[r:IN_FRUIT_SALAD]->(f1:Fruit)-[:IS_APPLE]->(tof)
WITH DISTINCT f, tof, COLLECT(DISTINCT f1) AS f1
WHERE ((tof)<-[:IS_BANANA]-(f)-[:IN_FRUIT_SALAD]->(:Fruit)-[:IS_APPLE]->(tof)) OR ((tof)<-[:IS_APPLE]-(f) AND NOT (f)<-[:IN_FRUIT_SALAD]-())
RETURN { fruit : f, fruitSaladComponents : f1 }

如果有人知道更好的解决方案,请告知。