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

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

  • 父/子类型节点,子节点与父节点具有相同的标签,因此是主结果中的有效项

  • 但如果将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 }

所以我想回来:

  • 香蕉是苹果水果沙拉的一部分

  • 不属于香蕉水果沙拉的苹果

  • "children"用香蕉制作水果沙拉的苹果

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

我认为可能有一种方法可以做到这一点涉及Collection FILTER ing,但我无法使它工作 .

我已经尝试将此作为 UNION (并使用 MATCH 而不是 OPTIONAL MATCH ),这可能是我最接近的结果,但是由于 UNION 中的每个查询都是原子的,我最终不得不重复逻辑另一个查询,我认为必须有一种方法来做到这一点,没有 UNION .

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

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

在那里你会看到 UNION 查询返回我想要使用 UNION 的结果,因为有条件我需要根据 UNION 的第一部分的结果进行过滤加上我不想要添加一个新的 UNION 每次我添加一个新的水果和香蕉不会永远是"parent" ...等等 -

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 }

更新26/05/2015:

以下查询有效,但有没有更好的方法 - 即 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)

3 years ago

解决方案与上面一样(稍微改动以移动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 }

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