2016-06-03 16 views
1

Ich habe eine Diagrammdatenbank, in der sich Benutzer- und Interessenknoten befinden, die durch IS_INTERESTED Beziehung verbunden sind. Ich möchte Interessen finden, die nicht von einem Benutzer ausgewählt werden. Ich diese Abfrage geschrieben und es funktioniert nichtCypher Query gibt keine nicht vorhandenen Beziehungen zurück

OPTIONAL MATCH (u:User{userId : 1})-[r:IS_INTERESTED] -(i:Interest) 
WHERE r is NULL 
Return i.name as interest 

Nach Antworten auf ähnliche Fragen auf SO (wie this eins), wird die obige Abfrage work.However soll, in diesem Fall es gibt null zurück. Aber wenn Sie die folgende Abfrage ausgeführt funktioniert es wie erwartet:

MATCH (u:User{userId : 1}), (i:Interest) 
WHERE NOT (u) -[:IS_INTERESTED] -(i) 
return i.name as interest 

Der Grund, warum ich will nicht die obige Abfrage auszuführen ist, weil Neo4j eine Warnung gibt:

Diese Abfrage erstellt ein kartesisches Produkt zwischen getrennten Mustern.

Wenn ein Teil einer Abfrage mehrere nicht verbundene Muster enthält, wird ein kartesisches Produkt zwischen all diesen Teilen erstellen. Dies kann eine große Menge an Daten produzieren und Abfrageverarbeitung verlangsamen. Während gelegentlich gedacht, ist es oft möglich sein kann, die Abfrage neu zu formulieren, die die Verwendung dieses Kreuzproduktes vermeidet, vielleicht durch eine Beziehung zwischen den verschiedenen Teilen Hinzufügen oder durch optionales MATCH mit (Kennung: (i))

Was mache ich falsch in der ersten Abfrage, wo ich OPTIONAL MATCH zu nicht vorhandenen Beziehungen zu finden?

Antwort

1

1) MATCH sucht das Muster als Ganzes, und wenn es nicht in seiner Gesamtheit finden kann - gibt nichts zurück.

2) Ich denke, dass diese Abfrage wirksam sein wird:

// Take all user interests 
MATCH (u:User{userId: 1})-[r:IS_INTERESTED]-(i:Interest) 
    WITH collect(i) as interests 
    // Check what interests are not included 
    MATCH (ni:Interest) WHERE NOT ni IN interests 
RETURN ni.name 
+0

Das ist ein kluger Weg! Es funktioniert jetzt. Vielen Dank! – avidProgrammer

0

Eine WHERE direkt nach dem OPTIONAL MATCH ist gezogen in die Auswertung.

Wenn Sie nachfiltern möchten, müssen Sie ein WITH dazwischen verwenden.

MATCH (u:User{userId : 1}) 
OPTIONAL MATCH (u)-[r:IS_INTERESTED] -(i:Interest) 
WITH r,i 
WHERE r is NULL 
Return i.name as interest 
+0

ich Ihre Antwort versucht, und es gibt nichts zurück. Es gibt nur die Nachricht _ (keine Änderungen, keine Zeilen) _ – avidProgrammer

1

Wenn Ihre OPTIONAL MATCH Abfrage keine Übereinstimmung finden, dann beide r UND i müssen NULL sein. Denn da es keine Beziehung gibt, gibt es keine Möglichkeit, die Knoten zu erhalten, auf die er zeigt.

+0

Ich sehe. Gibt es also einen besseren Weg (als die zweite Abfrage, die ich verwendet habe), um Interessen zu finden, die nicht von einem bestimmten Benutzer ausgewählt wurden? – avidProgrammer

+0

Ich sehe keinen besseren Weg. – cybersam

Verwandte Themen