Ich habe ein verknüpftes Listenmodell mit neo4j erstellt. Hier gibt es eine Darstellung:

Linked list of events

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
marc_aragones 23 Dez. 2015 im 15:57

2 Antworten

Beste Antwort

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;
1
Community 23 Mai 2017 im 11:52

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

1
David Makogon 23 Dez. 2015 im 13:50