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 пункт, чтобы потерпеть неудачу (который в свою очередь сделал бы userRel3NULL).

Другие вопросы по тегам