2016-07-02 15 views
1

Ich benutze Neo4J und lernen Cypher, und habe eine Frage zum Filtern von Ergebnissen basierend auf einem Attribut des ersten angetroffenen Knotens eines bestimmten Typs (in der OPTIONAL MATCH Zeile des Beispielcodes unten).Kann Cypher Ergebnisse basierend auf einem Attribut des ersten gefundenen Knotens eines bestimmten Typs filtern?

Meine Frage lautet wie folgt:

MATCH 
    (a:Word), 
    (b:Word) 
WHERE a.lemma IN [ "enjoy" ] 
    AND b.lemma IN [ "control", "achievement" ] 
OPTIONAL MATCH p = shortestPath((a)-[:IS_DEFINED_AS|IS_A_FORM_OF*..15]-(b)) 
RETURN 
    a.lemma as From, b.lemma as To, 
    length(
    filter(n in nodes(p) WHERE 'Word' in labels(n)) 
) - 1 as Shortest_Number_of_Hops_Only_Counting_Words, 
    length(p) as Shortest_Number_of_Hops_Counting_All_Nodes 

Zwei allgemeine Typen von Pfaden können in der Datenbank auftreten:

(a:Word) <-[IS_A_FORM_OF]- (Morph) -[IS_A_FORM_OF]-> (Word) -[IS_DEFINED_AS]-> (Synset) <-[IS_DEFINED_AS]- (Word) -[IS_DEFINED_AS]-> (Synset) <-[IS_DEFINED_AS]- (b:Word) 

und

(a:Word) -[IS_DEFINED_AS]-> (Synset) <-[IS_DEFINED_AS]- (Word) -[IS_DEFINED_AS]-> (Synset) <-[IS_DEFINED_AS]- (b:Word) 

Es kann eine beliebige Anzahl von Sprüngen sein (derzeit in der obigen Abfrage auf 15 begrenzt) zwischen a und b.

Ich habe versucht, ein sehr spezifisches Beispiel oben zu geben, aber meine Frage ist wirklich eine sehr allgemeine über die Verwendung von Cypher: Ich möchte nach Pfaden filtern, in denen der erste gefundene Synset Knoten ein bestimmtes Attribut enthält (z Beispiel {part_of_speech: 'verb'} Ich habe die Cypher refcard gelesen und frage mich, ob der Ausdruck head() verwendet werden sollte, um irgendwie den ersten Synset-Knoten im Pfad auszuwählen, aber ich bin mir nicht sicher, wie das geht dies dem MATCH/WHERE-Anweisung?

Antwort

0

@ oleg-Kurbatov Antwort funktioniert funktioniert, aber nur wenn (a: Word) sofort mit einem Synset verbunden ist (es berücksichtigt nicht Fälle, in denen (a: Word) durch einen Knoten vom Typ Morph usw. laufen muss, bevor es zu einem Synset kommt wie in meinem ersten Beispielpfad in der ursprünglichen Frage). Zusätzlich scheint der adding-paths-together-Ansatz zu sein rechenintensiver - 802ms für meine ursprüngliche Abfrage vs 2364ms eine leicht modifizierte Version von Oleg vorgeschlagenen Umsetzung mit (seit Cypher/Neo4j erlaubt nicht mehr als einen bestimmten Hop angeben, wenn shortestPath() mit:

MATCH 
    (a:Word), 
    (b:Word) 
WHERE a.lemma IN [ "enjoy" ] 
    AND b.lemma IN [ "control", "achievement" ] 
MATCH p1 = (a)-[:IS_DEFINED_AS]-> (initial_synset:Synset{pos: 'v'}) 
OPTIONAL MATCH p2 = shortestPath((initial_synset)-[:IS_DEFINED_AS|IS_A_FORM_OF*..15]-(b)) 
RETURN 
    a.lemma as From, b.lemma as To, 
    length(
    filter(n in nodes(p2) WHERE 'Word' in labels(n)) 
) as Shortest_Number_of_Hops_Only_Counting_Words, 
    length(p1) + length(p2) as Shortest_Number_of_Hops_Counting_All_Nodes 

Olegs Taking Vorschlag als Als Ausgangspunkt habe ich jedoch einen Weg gefunden, shortestPath() so zu filtern, dass er nur auf einem Pfad abgerechnet wird, auf dem der zuerst gefundene Synset-Knoten ein "pos" -Attribut von "v" hat, ohne die Abfrageausführungszeit zu erhöhen: Ich habe die OPTIONAL MATCH geändert Linie in meiner ursprünglichen Frage zu lesen:

OPTIONAL MATCH p = shortestPath((a)-[:IS_DEFINED_AS|IS_A_FORM_OF*..15]-(b)) 
WHERE head(filter(x in nodes(p) WHERE x:Synset)).pos = 'v' 

Wie ich weiß, erhält filter(x in nodes(p) WHERE x:Synset) eine Liste aller Knoten vom Synset-Typ in dem betrachteten Pfad.head(...) ruft den ersten Knoten aus dieser Liste ab, und .pos = 'v' überprüft, ob das "pos" -Attribut dieses Knotens "v" ist.

0

Sie können durch ihre Eigenschaft wie folgt

0 Synset Knoten entsprechen

Dann wird die Variable verb nur mit Synset-Knoten übereinstimmen, deren part_of_speech-Eigenschaft "verb" ist.

Sie können diese Variable in Ihrer Anfrage weiter verwenden. Zum Beispiel können Sie im Wesentlichen die gleiche Anforderung schreiben den Wert des Knotens Eigenschaft in WHERE Abschnitt zu beschränken:

MATCH (verb:Synset) 
WHERE verb.part_of_speech = 'verb' 
RETURN verb 

auf Ihre Anfrage Anwenden Sie könnte es wie folgt umschreiben:

MATCH 
    (a:Word) -[:IS_DEFINED_AS]-> (verb:Synset {part_of_speech: "verb"}), 
    (b:Word) 
WHERE a.lemma IN [ "enjoy" ] 
    AND b.lemma IN [ "control", "achievement" ] 
OPTIONAL MATCH p = shortestPath((a)-[:IS_DEFINED_AS]-(verb)-[:IS_DEFINED_AS|IS_A_FORM_OF*..15]-(b)) 
RETURN 
    a.lemma as From, b.lemma as To, 
    length(
    filter(n in nodes(p) WHERE 'Word' in labels(n)) 
) - 1 as Shortest_Number_of_Hops_Only_Counting_Words, 
    length(p) as Shortest_Number_of_Hops_Counting_All_Nodes 
+1

Vielen Dank für Ihren Vorschlag! Das hat mir viel bei der Konstruktion der Antwort geholfen, die ich unten gefunden habe. Ich habe erst erkannt, dass es möglich ist, mit Cypher Pfade hinzuzufügen. Ich bin dankbar für deine Hilfe:) –