2012-06-08 9 views
52

Ich versuche, eine Abfrage mit Chiffre zu erstellen, die „Find“ fehlende Zutaten, die ein Koch haben könnte, ist mein Graph wie so ein:Return Knoten, wenn Beziehung nicht vorhanden ist

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

(ingredient) würde habe einen Schlüssel/Wert von name = "dye colors". (ingredient_value) könnte einen Schlüssel/Wert von Wert = "rot" haben und "ist Teil von" (ingredient, name="dye colors").

(chef)-[:has_value]->(ingredient_value)<-[:requires_value]-(recipe)-[:requires_ingredient]->(ingredient) 

Ich verwende diese Abfrage alle ingredients zu bekommen, aber nicht ihre tatsächlichen Werte, dass ein Rezept erfordert, aber ich würde die Rückkehr möchte nur die ingredients, dass der Koch nicht hat, statt den ganzen Zutaten, die jedes Rezept benötigt. Ich versuchte

(chef)-[:has_value]->(ingredient_value)<-[:requires_value]-(recipe)-[:requires_ingredient]->(ingredient)<-[:has_ingredient*0..0]-chef 

, aber dies ergab nichts.

Ist dies etwas, das mit cypher/neo4j erreicht werden kann, oder ist das etwas, das am besten gehandhabt wird, indem alle Zutaten zurückgegeben und durch sie selbst sortiert werden?

Bonus: Es gibt auch eine Möglichkeit, Chiffre zu verwenden, um alle Werte, die ein Koch hat, mit allen Werten zu vergleichen, die ein Rezept benötigt. Bis jetzt habe ich nur alle Teiltreffer zurückgegeben, die von einer chef-[:has_value]->ingredient_value<-[:requires_value]-recipe zurückgegeben werden und die Ergebnisse selbst aggregieren.

+0

hier prüft relevante Informationen v3: http://stackoverflow.com/questions/25673223/finding-nodes-that-do-not-have-specific- Beziehung-Chiffre-Neo4j – Maciej

Antwort

106

-Update 2013.01.10:

über diese in der Neo4j Came 2.0 Referenz:

Versuchen nicht optional Beziehungen zu verwenden. Vor allem

sie nicht wie diese verwenden:

MATCH a-[r?:LOVES]->() WHERE r IS NULL, wo Sie nur sicherstellen, dass sie nicht existieren.

Statt dies tun, wie so:

MATCH a WHERE NOT (a)-[:LOVES]->() 

Chiffre Verwendung zu überprüfen, ob Beziehung existiert nicht:

... 
MATCH source-[r?:someType]-target 
WHERE r is null 
RETURN source 

Die? Markierung macht die Beziehung optional.

ODER

In Neo4j 2 tun:

... 
OPTIONAL MATCH source-[r:someType]-target 
WHERE r is null 
RETURN source 

Jetzt können Sie überprüfen, für nicht vorhandene (null) Beziehung.

+3

Verwenden Sie in Neo4j 2.0 OPTIONAL MATCH, um optionale Beziehungen abzubilden, dh das erste Beispiel würde aussehen wie OPTIONAL MATCH (Quelle) - [R: SomeType] - (Ziel) RETURN Quelle, r – boggle

+0

Ich versuche, einen markierten Knoten zu haben In WO NICHT, es funktioniert nicht. Wie: Letztes Spiel WHERE NOT (a) - [: LIEBT] -> (Fremder), in diesem 'Fremder' ein Knoten-Label ist. Ich verwende Neo4j Version 2.1.2 –

+0

Könnten Sie diese Antwort ändern, um die Aktualisierung zu reflektieren? – NumenorForLife

1

sollte die letzte Abfrage sein:

START chef = node(..) 
MATCH (chef)-[:has_value]->(ingredient_value)<-[:requires_value]-(recipe)-[:requires_ingredient]->(ingredient) 
WHERE (ingredient)<-[:has_ingredient]-chef 
RETURN ingredient 

Dieses Muster: (ingredient)<-[:has_ingredient*0..0]-chef

ist der Grund, es nicht etwas zurückgekommen. *0..0 bedeutet, dass die Länge der Beziehungen Null sein muss, was bedeutet, dass Zutat und Chef derselbe Knoten sein müssen, was sie nicht sind.

+0

Ja, aber es nicht die gewünschte Zutat zurück. Es bringt zurück, was der Koch bereits mit dem Rezept gemein hat, ich will den Unterschied herausfinden. – Nicholas

2

Ich habe diese Aufgabe mit Gremlin abgeschlossen. Ich tat

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() 

Dies ergab die Pfade aller fehlenden Zutaten. Das konnte ich in der Chiffre-Sprache zumindest für die Version 1.7 nicht formulieren.

2

Ich schrieb einen Kern zeigt, wie dies ganz natürlich Cypher getan werden kann 2,0

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

Der entscheidende Punkt ist optional Match verfügbaren Zutaten zu verwenden und dann für fehlende (null) Zutaten filtern vergleichen oder Zutaten mit dem falschen Wert.

Beachten Sie, dass der Begriff deklarativ ist und keinen Algorithmus beschreiben muss, Sie schreiben einfach auf, was Sie brauchen.

10

Bei Knoten mit nicht jeder Beziehung

Das ist die gute Option Abrufen Beziehung zu überprüfen ist, existieren oder nicht

MATCH (player)-[r:played]->() 
    WHERE r IS NULL 
    RETURN player 

Sie auch mehrere Bedingungen für diese überprüfen Es werden alle Knoten zurückkehren, die nicht "gespielt" oder "nicht gespielt" Beziehung.

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

Knoten abzurufen, die jede nicht mit realtionship

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

Es wird Prüfknoten keine eingehenden/ausgehende Beziehung aufweisen.

+2

MATCH (Spieler) WHERE NOT (Spieler) - [r] -() RETURN player' ** Variable r nicht definiert gibt ** Fehler. Wie kann ich r definieren? –

5

Wenn Sie "bedingte Ausschluss" Semantik benötigen, können Sie es auf diese Weise erreichen.

Ab neo4j 2.2.1 können Sie die OPTIONAL MATCH-Klausel verwenden und die nicht übereinstimmenden Knoten (NULL) filtern.

Es ist auch wichtig WITH Klausel zwischen den OPTIONAL MATCH und WHERE Klauseln zu verwenden, so dass WHERE verhält sich wie ein Filter, die nicht Teil der Übereinstimmungsmuster mögen.

Angenommen, wir haben 2 Arten von Knoten: Person und Communication.Wenn ich alle Personen zu bekommen, die nie von dem Telefon kommuniziert haben, aber auch andere Wege mitgeteilt haben kann, würde ich diese Abfrage machen:

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

Beachten Sie, dass die erste WHERE Klausel wie ein Teil des Spiels verhält.

Referenzen:

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