Как агрегировать результат 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))
Другие вопросы по тегам