如果关系不存在,则返回节点
我试图使用密码来创build一个查询,将“查找”一个厨师可能有的缺less的成分,我的graphics是这样设置的:
(ingredient_value)-[:is_part_of]->(ingredient)
(ingredient)
将具有名称=“染料颜色”的键/值。 (ingredient_value)
可以具有值=“红色”和“是(ingredient, name="dye colors")
一部分”的键/值。
(chef)-[:has_value]->(ingredient_value)<-[:requires_value]-(recipe)-[:requires_ingredient]->(ingredient)
我使用这个查询来获得食谱所需要的所有ingredients
,但不是它们的实际值,但是我希望返回只有厨师没有的成分,而不是每个食谱需要的所有成分。 我试过了
(chef)-[:has_value]->(ingredient_value)<-[:requires_value]-(recipe)-[:requires_ingredient]->(ingredient)<-[:has_ingredient*0..0]-chef
但是这没有任何回报。
这是可以通过cypher / neo4j完成的东西吗?或者这是最好通过返回所有成分并通过它们自己sorting来处理的东西?
奖金:还有一种方法可以使用密码来匹配厨师拥有的所有值,这是配方需要的。 到目前为止,我只返回了由chef-[:has_value]->ingredient_value<-[:requires_value]-recipe
返回的所有部分匹配chef-[:has_value]->ingredient_value<-[:requires_value]-recipe
并自己汇总结果。
2013年10月10日更新:
在Neo4j 2.0参考中遇到这个问题:
尽量不要使用可选关系。 首先,
不要像这样使用它们:
MATCH a-[r?:LOVES]->() WHERE r IS NULL
在那里你只要确保它们不存在。
而是这样做:
MATCH a WHERE NOT (a)-[:LOVES]->()
使用密码来检查关系是否不存在:
... MATCH source-[r?:someType]-target WHERE r is null RETURN source
这个? 标记使关系可选。
要么
在neo4j 2中:
... OPTIONAL MATCH source-[r:someType]-target WHERE r is null RETURN source
现在你可以检查不存在(null)的关系。
用于获取没有任何关系的节点
这是检查关系是否存在的好select
MATCH (player)-[r:played]->() WHERE r IS NULL RETURN player
您也可以检查多个条件这将返回所有节点,没有“播放”或“notplayer”的关系。
MATCH (player) WHERE NOT (player)-[:played|notPlayed]->() RETURN player
获取没有任何关系的节点
MATCH (player) WHERE NOT (player)-[r]-() RETURN player
它将检查没有任何传入/传出关系的节点。
如果你需要“有条件的排除”语义,你可以通过这种方式实现。
从neo4j 2.2.1开始,可以使用OPTIONAL MATCH
子句并过滤不匹配的( NULL
)节点。
在OPTIONAL MATCH
和WHERE
子句之间使用WITH
子句也很重要,这样WHERE
就像filter一样,不像匹配模式的一部分。
假设我们有两种types的节点: Person
和Communication
。 如果我想获得所有从来没有通过电话沟通的人,但可能已经通过其他方式进行沟通,我会提出这样的问题:
MATCH (p: Person) OPTIONAL MATCH p--(c: Communication) WHERE c.way = 'telephone' WITH p, c WHERE c IS NULL RETURN p
请注意,第一个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
关键是要对可用的成分使用可选的匹配,然后比较过滤缺失(空)成分或具有错误值的成分。
请注意,这个概念是声明性的,不需要描述一个algorithm,你只需要写下你所需要的。
我使用gremlin完成了这个任务。 我做了
x=[] g.idx('Chef')[[name:'chef1']].as('chef') .out('has_ingredient').as('alreadyHas').aggregate(x).back('chef') .out('has_value').as('values') .in('requires_value').as('recipes') .out('requires_ingredient').as('ingredients').except(x).path()
这返回了所有缺less的成分的path。 至less在1.7版本中,我无法用密码语言来expression这一点。
最后的查询应该是:
START chef = node(..) MATCH (chef)-[:has_value]->(ingredient_value)<-[:requires_value]-(recipe)-[:requires_ingredient]->(ingredient) WHERE (ingredient)<-[:has_ingredient]-chef RETURN ingredient
这种模式:( (ingredient)<-[:has_ingredient*0..0]-chef
是没有任何回报的原因。 *0..0
表示关系的长度必须为零,这意味着配料和厨师必须是同一个节点,而他们不是。