Ich habe ein verknüpftes Listenmodell mit neo4j
erstellt. Hier gibt es eine Darstellung:
Ein Benutzer hat eine Liste von Events
und jedes hat zwei Attribute: date
und done
. Zu einem bestimmten Zeitpunkt möchte ich das Attribut done
aller vorherigen Ereignisse auf true
setzen.
Meine aktuelle Anfrage lautet:
MATCH (user:User {id: {myId} })-[rel:PREV*]->(event:Event {done:false})
WHERE event.date <= {eventTime}
SET event.done = true;
Diese Abfrage dauert 12 Sekunden, wenn die Liste 500 Ereignisse enthält und ich sie schneller machen möchte. Eine Möglichkeit wäre, die Abfrage zu stoppen, sobald ein Ereignis gefunden wurde, das bereits ausgeführt wurde, aber ich weiß nicht, wie es zu tun ist.
2 Antworten
Sie können shortestPath
dafür verwenden und es wird viel schneller sein. Im Allgemeinen sollten Sie niemals [:REL_TYPE*]
verwenden, da eine umfassende Suche nach jedem Pfad mit beliebiger Länge zwischen den Knoten durchgeführt wird.
Ich habe Ihre Daten erstellt:
CREATE (:User {id:1})-[:PREV]->(:Event {id:1, date:1450806880004, done:false})-[:PREV]->(:Event {id:2, date:1450806880003, done:false})-[:PREV]->(:Event {id:3, date:1450806880002, done:true})-[:PREV]->(:Event {id:4, date:1450806880002, done:true});
Die folgende Abfrage findet dann alle vorherigen Ereignisknoten in der verknüpften Liste eines bestimmten Benutzers, wobei done = false ist und das Datum kleiner oder gleich beispielsweise 1450806880005 ist.
MATCH p = shortestPath((u:User)-[:PREV*]->(e:Event))
WHERE u.id = 1 AND
e.done = FALSE AND
e.date <= 1450806880005
RETURN p;
Dies ergibt:
p
[(6:User {id:1}), (6)-[6:PREV]->(7), (7:Event {date:1450806880004, done:false, id:1})]
[(6:User {id:1}), (6)-[6:PREV]->(7), (7:Event {date:1450806880004, done:false, id:1}), (7)-[7:PREV]->(8), (8:Event {date:1450806880003, done:false, id:2})]
Sie können also sehen, dass zwei Pfade zurückgegeben werden, einer, der bei Event mit id = 1 endet, und einer, der bei Event mit id = 2 endet.
Dann können Sie so etwas tun:
MATCH p = shortestPath((u:User)-[:PREV*]->(e:Event))
WHERE u.id = 1 AND e.done = FALSE AND e.date <= 1450806880005
FOREACH (event IN TAIL(NODES(p)) | SET event.done = TRUE)
RETURN p;
Ich verwende TAIL hier, weil es alle Knoten außer dem ersten erfasst (da wir diese Eigenschaft für den Benutzerknoten nicht aktualisieren möchten). Jetzt wurden alle erledigten Eigenschaften auf den Ereignisknoten aktualisiert:
p
[(6:User {id:1}), (6)-[6:PREV]->(7), (7:Event {date:1450806880004, done:true, id:1})]
[(6:User {id:1}), (6)-[6:PREV]->(7), (7:Event {date:1450806880004, done:true, id:1}), (7)-[7:PREV]->(8), (8:Event {date:1450806880003, done:true, id:2})]
EDIT: Und vergessen Sie nicht den super lustigen Fehler, bei dem die Funktion shortestPath
das maximale Hop-Limit in Neo4j & lt; 2.3.0. Sehen
ShortestPath findet keinen Pfad ohne maximales Hopfenlimit
Finde alle Events zwischen 2 Terminen
Wenn Sie also mit Neo4j <2.3.0 arbeiten, sollten Sie Folgendes tun:
MATCH p = shortestPath((u:User)-[:PREV*..1000000000]->(e:Event))
WHERE u.id = 1 AND e.done = FALSE AND e.date <= 1450806880005
FOREACH (event IN TAIL(NODES(p)) | SET event.done = TRUE)
RETURN p;
Ihre Frage ist in Bezug auf Leistungsprobleme und -ziele ziemlich vage, aber eine wichtige Sache für die Leistung ist die Erstellung eines Index für die Eigenschaften, die Sie untersuchen. In Ihrem Fall würde dies bedeuten, einen Index sowohl für die Eigenschaft done
als auch für die Eigenschaft date
zu erstellen:
CREATE INDEX ON :Event(done)
CREATE INDEX ON :Event(date)
Darüber hinaus ruft Ihre Abfrage alle Ereignisse im gesamten Verlauf eines Benutzers ab, wie in:
-[rel:PREV*]->
Sie könnten die Tiefe begrenzen, wie z
-[rel:PREV*..20]->
Um eine vollständige Durchquerung zu verhindern. Das gibt Ihnen möglicherweise nicht das gewünschte Ergebnis, aber es würde lang laufende Abfragen verhindern, wenn Sie eine extreme Anzahl von Knoten in Ihrer verknüpften Liste haben (Sie haben nicht angegeben, wie groß diese Liste werden könnte, also habe ich keine Idee, ob dies tatsächlich helfen wird).
Neue Fragen
neo4j
Neo4j ist eine Open-Source-Grafikdatenbank (GDB), die sich gut für verbundene Daten eignet. Bitte geben Sie Ihre genaue Version von Neo4j an, wenn Sie Fragen stellen. Sie können es für Empfehlungs-Engines, Betrugserkennung, grafische Suche, Netzwerkoperationen / -sicherheit und viele andere Benutzerfälle verwenden. Der Zugriff auf die Datenbank erfolgt über offizielle Treiber in Java, JavaScript, Python und .NET oder über von der Community bereitgestellte Treiber in PHP, Ruby, R, Golang, Elixir, Swift und anderen.