如果关系不存在,则返回节点

我试图使用密码来创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 MATCHWHERE子句之间使用WITH子句也很重要,这样WHERE就像filter一样,不像匹配模式的一部分。

假设我们有两种types的节点: PersonCommunication 。 如果我想获得所有从来没有通过电话沟通的人,但可能已经通过其他方式进行沟通,我会提出这样的问题:

 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表示关系的长度必须为零,这意味着配料和厨师必须是同一个节点,而他们不是。