Cypher Union группа по сумме
Я хотел бы увеличить ребра для пользователя в зависимости от некоторых правил на основе обхода графа. В основном в MySQL я бы сделал это:
select id, sum(weight) as total
from
(
select id, 10 as weight
from user
inner join userRel1 ON user.id = userRel1.userId
where userRel1.attr1 in (1, 2)
union
select id, 5 as weight
from user
inner join userRel2 ON user.id = userRel2.userId
inner join userRel3 ON user.id = userRel3.userId
where userRel2.attr2 = 'a' and userRel3.attr2 = 'z'
union
...
)
group by id
order by total desc
Кроме того, я уже написал этот запрос с некоторой помощью в gremlin 3, но я хотел бы сравнить производительность с шифром. Но я читал в этом посте, что группировка по объединению пока невозможна, это значит, что шифр менее мощный, чем гремлин? Должен ли я установить вес как свойства на краях, чтобы достичь этого?
Спасибо
1 ответ
Хотя это правда, что пост- UNION
обработка по- прежнему открытая функция запроса, вам не нужно использовать UNION
выполнить ваш вариант использования.
Этот запрос должен соответствовать вашему SQL (игнорируя незавершенную часть):
WITH [] AS res
OPTIONAL MATCH (user1:User), (userRel1:UserRel1)
WHERE user1.id = userRel1.userId AND userRel1.attr1 IN [1, 2]
WITH res, (CASE WHEN userRel1 IS NOT NULL THEN COLLECT({id: user1.id, weight: 10}) ELSE [] END) AS data
WITH res + data AS res
OPTIONAL MATCH (user2:User), (userRel2:UserRel2)
WHERE user2.id = userRel2.userId AND userRel2.attr2 = 'a'
OPTIONAL MATCH (userRel3:UserRel3)
WHERE user2.id = userRel3.userId AND userRel3.attr2 = 'z'
WITH res, (CASE WHEN userRel3 IS NOT NULL THEN COLLECT({id: user2.id, weight: 5}) ELSE [] END) AS data
WITH res + data AS res
UNWIND res AS result
RETURN result.id, SUM(result.weight) AS weight;
Я визуально разбил этот запрос на отдельные блоки Cypher, чтобы его было легче читать.
Запрос продолжает расширять (и заменять) res
Коллекция с соответствующими id
/ weight
пары, а затем агрегирует в конце.
Блок с 2 OPTIONAL MATCH
пункты могли быть написаны с использованием одного OPTIONAL MATCH
, но я подумал, что более эффективно выполнять ту же работу по частям, и допустить провал одного OPTIONAL MATCH
потенциально информировать Сайфера, чтобы он даже не беспокоился о другом. Блок второй WHERE
пункт опирается на user2
узел, который найден первым OPTIONAL MATCH
, user2
будет иметь значение NULL
если первый OPTIONAL MATCH
не удалось, и такая NULL
значение также вызовет второе WHERE
пункт, чтобы потерпеть неудачу (который в свою очередь сделал бы userRel3
NULL
).