2016-05-09 6 views
0

Die Knoten in meiner db sind wie folgt:Neo4j Abfrage erhalten führen ohne Duplizierung

(u : User)-[:HAVE_DONATED{amount, txnId, timestamp}]->(p : Project) 
(c : Company)-[:HAVE_DONATED{amount, txnId, timestamp}]->(p : Project) 

Ein Benutzer kann mehrfach und gleiche gilt für Unternehmen zu einem Projekt spenden. Ich speichere Transaktions-ID und Betrag in Relation, ist es eine gute Praxis? Jetzt muss ich eine Abfrage schreiben, die alle Projekte abruft, in denen ein Benutzer gespendet hat. Das Ergebnis sollte folgende Eigenschaften enthalten: projectId: {projectId, totalDonation (Spende von Benutzer + Unternehmen), totalDonor (Benutzer + Unternehmen), individualContribution (individueller Beitrag des Benutzers in diesem Projekt, wenn der Benutzer dann mehrfach gespendet hat es sollte alle Spenden zusammenfassen), donationTime (wenn der Benutzer mehrere Male für dasselbe Projekt gespendet hat, sollte er den letzten Zeitstempel auswählen)}.

Ich habe die Abfrage geschrieben, wenn Benutzer oder Firma nur einmal spenden können. Ich bekomme doppeltes Projekt, wenn Benutzer/Firma mehrfach spendet. Es folgt die Abfrage für einzelne Spende:

Match (u : User {id : {userId}})-[r:HAVE_DONATED]->(p : Project) with p,r 
where p.status IN ["2", "3"] OPTIONAL MATCH (c)-[r2:HAVE_DONATED]->(p) WITH 
p, COUNT(distinct(c)) as donors, SUM(TOINT(r2.amount)) AS donation, 
r.createdTimeStamp as timestamp, TOINT(r.amount) as individualContribution 
return distinct {totalDonation : donation, id : p.id, title : p.title, 
totalDonors : donors, donationTimeStamp : timestamp , contribution : 
individualContribution} as project order by project.donationTimeStamp desc 

Antwort

0

[EDITED]

dies Ihre Anforderungen erfüllen könnten:

MATCH (u:User {id: 123})-[r:HAVE_DONATED]->(p:Project) 
WHERE p.status IN ["2", "3"] 
OPTIONAL MATCH (c)-[r2:HAVE_DONATED]->(p) 
WHERE c <> u 
WITH p, 
    COALESCE(COUNT(distinct(c)), 0) AS c_donors, 
    COALESCE(SUM(TOINT(r2.amount)), 0) AS c_contribution, 
    MAX(r.createdTimeStamp) AS i_timestamp, 
    TOINT(r.amount) AS i_contribution 
RETURN { 
    totalDonation: c_contribution + i_contribution, 
    id: p.id, 
    title: p.title, 
    totalDonors: c_donors + 1, 
    donationTimeStamp: i_timestamp, 
    contribution: i_contribution 
} AS project 
ORDER BY project.donationTimeStamp DESC; 

Eine wichtige Verbesserung war die Spezifikation der der WHERE Klausel nach der OPTIONAL MATCH Klausel . Die Ausdrücke COALESCE verhindern, dass die Werte c_donors und c_contributionsNULL sind, wenn die OPTIONAL MATCH-Klausel keine Übereinstimmung findet. Ich nehme an, dass die Eigenschaft createdTimeStamp entweder numerisch ist (z. B. ein Epochenzeitstempel) oder ein Zeichenfolgenformat hat, das lexikalisch sortiert werden kann.

+0

Ein Projekt kann eine Spende vom Benutzer haben, aber in einer optionalen Übereinstimmung stimmen Sie nur mit dem Unternehmen überein, sodass totalDonation und totalDonors keinen Beitrag von anderen Nutzern als Unternehmen und übereinstimmenden Nutzern haben. – user3542450

+0

OK, siehe meine aktualisierte Antwort. – cybersam

+0

Ich habe 3 Knoten in meiner Datenbank. (u1: Benutzer) - [: HAVE_DONATED {Menge: 12332}] -> (p1: Projekt), (u2: Benutzer) - [: HAVE_DONATED {Anzahl: 100}] -> (p1: Projekt), (u2: Benutzer) - [: HAVE_DONATED {Menge: 12344}] -> (p1: Projekt). Der maximale Zeitstempel sollte vom passenden Benutzer sein, wenn er mehr als einmal gespendet hat und dann nach diesem Zeitstempel sortiert wurde. Ich bekomme nicht das richtige Ergebnis. http://postimg.org/image/3kyglgudd/ Bitte werfen Sie einen Blick auf diese URL. – user3542450