関係が存在しない場合はノードを返します


88

シェフが持っている可能性のある不足している材料を「見つける」サイファーを使用してクエリを作成しようとしています。グラフは次のように設定されています。

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

(ingredient)name = "dyecolors"のキー/値があります。 (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/…–
Maciej

将来のユーザーのために; 使用することができるexistsWHERE句(また、同様にそれを否定)、neo4j.com/developer/subqueries/#existential-subqueries詳細については。
ozanmuyes

回答:


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

これで、存在しない(null)関係を確認できます。


3
Neo4j 2.0では、使用OPTIONAL MATCHは、最初の例ではOPTIONAL MATCH(ソース)のようになり、すなわち、任意の関係と一致するよう- [R:someType] - (ターゲット)RETURN源、Rは
尻込み

WHERE NOTにラベル付きノードを作成しようとしていますが、機能しません。例:MATCH a WHERE NOT(a)-[:LOVES]->(Stranger)、この「ストレンジャー」はノードラベルです。私はneo4jバージョン2.1.2を使用しています
Krishna Shetty 2014

1
気にしないでください、私はあなたがこの答えに到達するために進行を示したい理由を理解しています:
どこにでも

4
MATCH a...例では、今でなければなりませんMATCH (a) WHERE NOT (a)-[:LOVES]->()
リアム・

1
@ gil-stalなぜこのようなクエリでノード名を使用できないのですか。一致する場所(a)-[:LOVES]->(b:SomeLabel)。ノード名を使用しない場合は機能します。
iit2011081 2017年

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 2017

関係(例えば指定のいずれか、この問題を解決するために(player -[:rel]- ())、または任意の関係のために空のままに(player -[]- ()
Archemar

MATCH (player) WHERE NOT (player)-[]-() RETURN player-
正常

最初のクエリは実際には間違っています。MATCHパターン自体は、常に既存の関係のみを返し、それらのいずれもNULLを返しません。したがって、WHERE行にはフィルタリングするものがありません。
Cristi S.

@CristiS。知らせてくれてありがとうございます。動作するはずのクエリを更新しました
Satish Shinde

8

「条件付き除外」セマンティクスが必要な場合は、この方法で実現できます。

neo4j 2.2.1以降、OPTIONAL MATCHclauseを使用して、unmatched(NULL)ノードを除外できます。

使用することも重要であるWITHとの間の句OPTIONAL MATCHWHERE、句を第1のそのWHERE定義するオプション一致するための条件と第二のWHEREフィルタのように振る舞います。

2種類のノードがあると仮定します:PersonCommunication。電話で通信したことはないが、他の方法で通信した可能性のあるすべての人を取得したい場合は、次のクエリを実行します。

MATCH (p: Person) 
OPTIONAL MATCH p--(c: Communication) 
WHERE c.way = 'telephone'
WITH p, c 
WHERE c IS NULL 
RETURN p

マッチパターンは、その通信に全員一致するcであろうNULL非電話通信のために。次にfilter(WHEREWITH)は、電話通信をフィルターで除外し、他のすべてを残します。

参照:

http://neo4j.com/docs/stable/query-optional-match.html#_introduction_3 http://java.dzone.com/articles/new-neo4j-optional


2

Cypher2.0を使用してこれを非常に自然に行う方法を示す要点を書きました

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

重要な点は、利用可能な材料とのオプションの一致を使用してから、欠落している(null)材料または間違った値の材料をフィルターで比較することです。

この概念は宣言型であり、アルゴリズムを記述する必要はなく、必要なものを書き留めるだけであることに注意してください。


2

私はグレムリンを使用してこのタスクを完了しました。やった

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つまり、関係の長さはゼロでなければなりません。つまり、食材とシェフは同じノードである必要がありますが、そうではありません。


はい、しかしそれは望ましい成分を返しません。シェフがすでにレシピと共通しているものを返しますので、違いを知りたいです。
ニコラス
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.