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


88

我正在尝试使用密码创建查询,以“查找”厨师可能缺少的食材,我的图形设置如下:

(ingredient_value)-[:is_part_of]->(ingredient)

(ingredient)的键/值将为name =“ dye colors”。 (ingredient_value)可能具有键/值value =“ red”,并且“是”的一部分(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来完成的事情,还是可以通过返回所有成分并自己对它们进行分类来最好地处理?

奖励:还有一种方法可以使用密码将厨师拥有的所有值与食谱所需的所有值进行匹配。到目前为止,我只返回了由a返回的所有部分匹配项,chef-[:has_value]->ingredient_value<-[:requires_value]-recipe并且自己汇总了结果。


检查这里的相关信息,以V3:stackoverflow.com/questions/25673223/...
马切伊

对于未来的用户;可以existsneo4j.com/developer/subqueries/#existential-subqueriesWHERE子句中使用(也可以对其进行否定)获取更多信息。
ozanmuyes

Answers:


157

2013年1月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

现在,您可以检查不存在的(空)关系。


3
在Neo4j的2.0,使用OPTIONAL MATCH匹配可选的关系,即,第一实施例将如下所示OPTIONAL MATCH(源) - [R:SOMETYPE] - (靶)RETURN源中,r
惊奇

我试图在WHERE NOT中有一个带标签的节点,它不起作用。像:匹配不在(a)-[:LOVES]->(Stranger)的地方,在这个“ Stranger”中是一个节点标签。我正在使用neo4j 2.1.2版
克里希纳·谢蒂

1
没关系,我理解您为什么想要显示进度以达到此答案:不匹配(a)-[:LOVES]->()
NumenorForLife 2015年

4
MATCH a...现在的示例应为MATCH (a) WHERE NOT (a)-[:LOVES]->()
Liam

1
@ gil-stal为什么这样的查询无法使用节点名称。匹配不在(a)-[:LOVES]->(b:SomeLabel)的地方。如果我不使用节点名,那么它将起作用。
iit2011081

15

用于获取没有任何关系的节点

这是检查关系是否存在的好选择

MATCH (player)
    WHERE NOT(player)-[:played]->()
    RETURN player

您也可以为此检查多个条件。它将返回所有没有“播放”或“未播放”关系的节点。

MATCH (player) 
 WHERE NOT (player)-[:played|notPlayed]->()
 RETURN player

提取没有任何关系的节点

MATCH (player) 
WHERE NOT (player)-[r]-()
RETURN player

它将检查节点没有任何传入/传出关系。


4
MATCH (player) WHERE NOT (player)-[r]-() RETURN player 给出变量r未定义错误。我如何定义r?
Chathura Wijeweera

要解决此问题,请指定一种关系(例如(player -[:rel]- ())或为任何关系留空(player -[]- ()
Archemar

MATCH (player) WHERE NOT (player)-[]-() RETURN player-工作正常
Prashanth Terala

您的第一个查询实际上是错误的。MATCH模式本身总是只返回现有关系,没有一个为NULL。因此,您的WHERE行没有要过滤的内容。
Cristi S.

@CristiS。谢谢你让我知道。我已经更新了它应该工作的查询
Satish Shinde

8

如果需要“条件排除”语义,则可以通过这种方式实现。

从neo4j 2.2.1开始,您可以使用OPTIONAL MATCH子句并过滤出unmatched (NULL)节点。

WITHOPTIONAL MATCHand子句之间使用子句也很重要WHERE,以便第WHERE一个为可选匹配定义条件,第二个WHERE行为像过滤器。

假设我们有两种类型的节点:PersonCommunication。如果我想让所有从未通过电话进行过交流但可能已经通过其他方式进行交流的人员,我将进行以下查询:

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


2

我写了一个要点,说明如何使用Cypher 2.0非常自然地完成此操作

http://gist.neo4j.org/?9171581

关键是使用与可用成分的可选匹配,然后进行比较以筛选缺失(空)成分或具有错误值的成分。

注意,该概念是声明性的,不需要描述算法,只需写下所需的内容即可。


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版,我无法用密码语言来表述。


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


是的,但是它没有返回所需的成分。它返回厨师已经在食谱上的共同点,我想找出区别。
尼古拉斯
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.