我尝试使用cypher创建一个查询,它将"查找"缺少厨师可能拥有的成分,我的图表设置如下:
(ingredient_value)-[:is_part_of]->(ingredient)
(ingredient)
将具有name ="染色"的键/值。 (ingredient_value)
可以有一个键值/值="红色"和"是"的一部分(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
返回的所有部分匹配并自行汇总结果。
答案 0 :(得分:135)
更新01/10/2013:
在Neo4j 2.0 参考中遇到过这个:
尽量不要使用可选关系。 最重要的是,
不要像这样使用它们:
MATCH a-[r?:LOVES]->() WHERE r IS NULL
您只需确保它们不存在。
而是这样做:
MATCH a WHERE NOT (a)-[:LOVES]->()
使用cypher检查关系是否不存在:
...
MATCH source-[r?:someType]-target
WHERE r is null
RETURN source
? mark使关系成为可选的。
OR
在neo4j 2中:
...
OPTIONAL MATCH source-[r:someType]-target
WHERE r is null
RETURN source
现在您可以检查不存在的(null)关系。
答案 1 :(得分:13)
用于获取没有任何关系的节点
这是检查关系是否存在的好选择
MATCH (player)-[r:played]->()
WHERE r IS NULL
RETURN player
您还可以检查多个条件 它将返回所有没有“播放”或“未播放”关系的节点。
MATCH (player)
WHERE NOT (player)-[:played|notPlayed]->()
RETURN player
获取没有任何真实性的节点
MATCH (player)
WHERE NOT (player)-[r]-()
RETURN player
它将检查节点没有任何传入/传出关系。
答案 2 :(得分:7)
如果您需要&#34;条件排除&#34;语义,你可以通过这种方式实现它。
从neo4j 2.2.1开始,您可以使用OPTIONAL MATCH
子句并过滤掉不匹配的(NULL
)节点。
在WITH
和OPTIONAL MATCH
子句之间使用WHERE
子句也很重要,这样第一个WHERE
定义了可选匹配的条件,第二个WHERE
{1}}的行为类似于过滤器。
假设我们有两种类型的节点:Person
和Communication
。如果我想让所有从未通过电话沟通但可能已经通过其他方式沟通的人员,我会提出这个问题:
MATCH (p: Person)
OPTIONAL MATCH p--(c: Communication)
WHERE c.way = 'telephone'
WITH p, c
WHERE c IS NULL
RETURN p
匹配模式将匹配所有与其通信的人员,c
将NULL
用于非电话通信。然后,过滤器(WHERE
之后的WITH
)将过滤掉所有其他人的电话通信。
参考文献:
http://neo4j.com/docs/stable/query-optional-match.html#_introduction_3 http://java.dzone.com/articles/new-neo4j-optional
答案 3 :(得分:2)
最后一个查询应该是:
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
表示关系的长度必须为零,这意味着成分和厨师必须是同一个节点,而不是它们。
答案 4 :(得分:2)
我使用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()
这返回了所有缺失成分的路径。我无法用密码语言表达这一点,至少对于1.7版本。
答案 5 :(得分:2)
我写了一篇小说,展示了如何使用Cypher 2.0自然地完成这项工作
http://gist.neo4j.org/?9171581
关键是要对可用成分使用可选匹配,然后比较过滤掉缺少(空)成分或成分的错误值。
请注意,这个概念是声明性的,不需要描述算法,只需写下你需要的内容。