2016-05-09 2 views
0

Узлы в моей БД следующим образом:Neo4j запрос, чтобы получить результат без дублирования

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

пользователь может пожертвовать на проект несколько раз и то же самое для компании. Я храню идентификатор транзакции и сумму в отношении, это хорошая практика? Теперь я должен написать запрос, который извлекает весь проект, в котором пользователь сделал пожертвование. Результат также должен содержать следующие свойства вместе с projectId: {projectId, totalDonation (пожертвование, сделанное пользователем + компании), totalDonor (пользователь + компании), individualContribution (индивидуальный вклад пользователя в этот проект, если пользователь пожертвовал несколько раз тогда он должен суммировать все пожертвования), donationTime (если пользователь пожертвовал несколько раз для того же проекта, тогда он должен выбрать последнюю временную метку)}.

Я написал запрос, когда пользователь или компания могут пожертвовать только один раз. Я получаю дублирующий проект, когда пользователь/компания несколько раз жертвует. Ниже приводится запрос для одного пожертвования:

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 

ответ

0

[Изменено]

Это может соответствовать вашим требованиям:

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; 

Одно важное усовершенствование было спецификация оговорки WHERE после пункта OPTIONAL MATCH , Выражения COALESCE предупреждают, что значения c_donors и c_contributions составляют NULL, если предложение OPTIONAL MATCH не может найти совпадение. Я предполагаю, что свойство createdTimeStamp является либо числовым (например, временной отметкой эпохи), либо имеет строковый формат, который может быть отсортирован лексически.

+0

Проект может иметь пожертвование от пользователя, но в факультативном совпадении вы соответствуете только Компании, поэтому totalDonation и totalDonors не будут иметь участия от других пользователей, кроме компаний и соответствующих пользователей. – user3542450

+0

ОК, см. Мой обновленный ответ. – cybersam

+0

У меня есть 3 узла в моем db. (u1: Пользователь) - [: HAVE_DONATED {amount: 12332}] -> (p1: Project), (u2: User) - [: HAVE_DONATED {amount: 100}] -> (p1: Project), (u2: User) - [: HAVE_DONATED {amount: 12344}] -> (p1: Project). Максимальная временная метка должна соответствовать совпадающему пользователю, если он/она пожертвовал более одного раза, а затем сортировать в соответствии с этой меткой времени. Я не получаю правильный результат. http://postimg.org/image/3kyglgudd/ Пожалуйста, взгляните на этот URL. – user3542450

Смежные вопросы