Как агрегировать результат Union in Cypher?
Я пытаюсь выяснить, как агрегировать результат Union in Cypher. Следующий пример может быть выполнен в фрагментах Cypher live:
MATCH (n:Crew)-[r:KNOWS]->m
WHERE n.name='Neo'
RETURN n AS name,m
UNION
MATCH (n:Crew)-[r:KNOWS]->m
WHERE n.name='Morpheus'
RETURN n AS name,m
Этот запрос показывает три строки как результат, потому что Нео знает одного человека, а Морфеус два (обратите внимание на направленную ссылку в запросе). Допустим, мы хотим объединить известных людей. Мы можем сделать что-то вроде этого:
MATCH (n:Crew)-[r:KNOWS]->m
WHERE n.name='Neo'
RETURN n AS name,count(m) AS c
UNION
MATCH (n:Crew)-[r:KNOWS]->m
WHERE n.name='Morpheus'
RETURN n AS name,count(m) AS c
Пока все в порядке. Тем не менее, я не знаю, как решить проблему, если то, что мы хотим объединить (скрытый Group By), находится как в первом, так и во втором запросе. Так как в предыдущем случае этого не происходит, давайте предположим, для объяснения, что у нас есть следующие запросы:
MATCH (n:Label1)-[:label3]->(:label4)
RETURN n.name as name, n.age as value
а также
MATCH (m:Label2)-[:label5]->(:label6)
RETURN m.surname as name, m.k as value
которые возвращаются
John, 12
Sam, 17
а также
John, 78
Tim, 12
Можно ли сделать что-то вроде
(
MATCH (n:Label1)-[:label3]->(:label4)
RETURN n.name as name, n.age as value
UNION ALL
MATCH (m:Label2)-[:label5]->(:label6)
RETURN m.surname as name, m.k as value
)
RETURN name, sum(value)
получить результат ниже?
John, 90
Sam, 17
Tim, 12
Очевидно, я уже пробовал такой запрос, и он не компилируется. Следовательно, мне интересно, есть ли что-то подобное.
2 ответа
На сегодняшний день вы не можете выполнять агрегирование для комбинированного набора результатов UNION
,
Единственный способ обойти это, избегая UNION
в пользу более сложного WHERE
:
MATCH (n)-[r:label3|label5]->(m)
WHERE ((type(r)='label3') AND ("Label1" in labels(n)) AND ("label4" in labels(m))) OR
((type(r)='label5') AND ("Label2" in labels(n)) AND ("label6" in labels(m)))
RETURN n.name as name, sum(n.age)
Как вы можете видеть здесь, вы можете использовать предложения COLLECT и UNWIND:
MATCH (n:Crew)-[r:KNOWS]->(m)
WHERE n.name='Neo'
WITH COLLECT({name:n, id:ID(m)}) as rows
MATCH (n:Crew)-[r:KNOWS]->(m)
WHERE n.name='Morpheus'
WITH rows + COLLECT({name:n,id:ID(m)}) as allRows
UNWIND allRows as row
RETURN row.name, count(disntict(row.id))