我正在尝试使用cypher创建一个查询,它将“查找”厨师可能缺少的成分,我的图形设置如下:
(ingredient_value)-[:is_part_of]->(ingredient)
(ingredient)
将具有name = "dye colors"的键/值 . (ingredient_value)
可以具有值= "red"和"is part of" (ingredient, name="dye colors")
的键/值 .
(chef)-[:has_value]->(ingredient_value)<-[:requires_value]-(recipe)-[:requires_ingredient]->(ingredient)
我正在使用此查询来获取食谱所需的所有 ingredients
,但不是它们的实际值,但我希望仅返回厨师没有的 ingredients
,而不是每个食谱所需的所有成分 . 我试过了
(chef)-[:has_value]->(ingredient_value)<-[:requires_value]-(recipe)-[:requires_ingredient]->(ingredient)<-[:has_ingredient*0..0]-chef
但这没有任何回报 .
这是可以通过cypher / neo4j完成的事情,还是通过返回所有成分并通过它们自行排序来最好地处理这个问题?
额外奖励:还有一种方法可以使用cypher来匹配厨师拥有的所有值以及配方所需的所有值 . 到目前为止,我只返回了 chef-[:has_value]->ingredient_value<-[:requires_value]-recipe
返回的所有部分匹配并自行汇总结果 .
6 回答
Update 01/10/2013:
在Neo4j 2.0 参考中遇到过这个:
尽量不要使用可选关系 . 首先,
don’t use them like this:
MATCH a-[r?:LOVES]->() WHERE r IS NULL
你只是确保它们不存在 .Instead do this like so:
使用cypher检查关系是否不存在:
的? mark使关系成为可选的 .
要么
在neo4j 2中:
现在您可以检查不存在的(null)关系 .
用于获取没有任何关系的节点
这是检查关系是否存在的好选择
您还可以检查多个条件 . 它将返回所有节点,这些节点没有“播放”或“未播放”关系 .
获取没有任何实现的节点
它将检查节点没有任何传入/传出关系 .
如果您需要“条件排除”语义,您可以通过这种方式实现它 .
从neo4j 2.2.1开始,您可以使用
OPTIONAL MATCH
子句并过滤掉不匹配的(NULL
)节点 .在
OPTIONAL MATCH
和WHERE
子句之间使用WITH
子句也很重要,这样第一个WHERE
定义了可选匹配的条件,第二个WHERE
就像过滤器一样 .假设我们有两种类型的节点:
Person
和Communication
. 如果我想让所有从未通过电话沟通但可能已通过其他方式传达的人员,我会提出以下问题:匹配模式将匹配所有人与他们的通信,其中
c
将NULL
用于非电话通信 . 然后过滤器(WITH
之后的WHERE
)将过滤掉所有其他电话通信 .参考文献:
http://neo4j.com/docs/stable/query-optional-match.html#_introduction_3 http://java.dzone.com/articles/new-neo4j-optional
我写了一篇关于如何使用Cypher 2.0自然地完成这一工作的要点
http://gist.neo4j.org/?9171581
关键点是对可用成分使用可选匹配,然后比较过滤缺失(无效)成分或成分的错误值 .
请注意,这个概念是声明性的,不需要描述算法,只需写下您需要的内容即可 .
我使用gremlin完成了这个任务 . 我做到了
这返回了所有缺失成分的路径 . 我无法用密码语言来表达这一点,至少对于1.7版本 .
最后一个查询应该是:
这种模式:
(ingredient)<-[:has_ingredient*0..0]-chef
是它没有返回任何东西的原因 .
*0..0
表示关系的长度必须为零,这意味着成分和厨师必须是同一个节点,而它们不是 .