Возврат узла после агрегирования в Cypher - PullRequest
2 голосов
/ 21 февраля 2020

Мне трудно понять, как правильно использовать агрегатные функции в Cypher.

Допустим, у меня есть узлы, помеченные как Animal, со свойствами size и species. Для каждого вида я хочу получить самый большой.

Пока я понимаю, что могу сделать это со следующим:

MATCH (n:Animal)
WITH n.species as species, max(n.size) as size
RETURN species, size

И я эффективно получу самые большие размеры с соответствующими видами .

Но как я могу получить узлы вместо видов?

Я не могу вернуть n из-за оператора WITH и не могу вставить его в WITH потому что это нарушит агрегацию species.

Я знаю, что этот вопрос уже задавался несколько раз, но различные решения, с которыми я столкнулся, были специфичны для конкретного случая c и использовали отношения

Любой совет очень приветствуется

РЕДАКТИРОВАТЬ: я наконец-то заставил его работать с:

MATCH (n:Animal)
WITH n.species as species, max(n.size) as size, collect(n) as ns
UNWIND ns as n
WITH n
WHERE n.size = size
RETURN n

Является ли это Cypher-способ урегулирования вещей? Мне кажется, это многословно и неэффективно (все узлы извлекаются здесь), разве нет более простого варианта?

Ответы [ 2 ]

2 голосов
/ 28 февраля 2020

Это часто встречающееся ограничение с нашими функциями агрегации max () и min (), поэтому мы добавили APO C функцию , которая может помочь: apoc.agg.maxItems():

apo c .agg.maxItems (item, value, groupLimit: -1) - возвращает карту {items: [], value: n}, где value - максимальное имеющееся значение, а items - все предметы с одинаковым значением. Количество предметов может быть ограничено.

MATCH (n:Animal)
WITH n.species as species, apoc.agg.maxItems(n.size, n) as sizeData
RETURN species, sizeData.value as size, sizeData.items as animals
2 голосов
/ 21 февраля 2020

Поскольку функция агрегации MAX не возвращает узел с максимальным значением, его не следует использовать. В противном случае вам придется проверить размер каждого животного дважды , чтобы получить максимальное значение и интересующий узел (как вы обнаружили).

Вместо этого вы можете использовать REDUCE Функция для проверки размера каждого животного только один раз:

MATCH (n:Animal)
WITH n.species AS species, COLLECT(n) as ns
RETURN species, REDUCE(s = {size: -1}, a IN ns |
  CASE WHEN a.size > s.size THEN {size: a.size, a: a} ELSE s END
) AS result;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...