#arrays #cypher #nested-lists #neo4j-apoc #unwind
Вопрос:
Я создаю 3 тестовых узла со свойствами имен «a», «b», «c» и использую apoc.coll.zip()
их для объединения двух списков вместе:
MATCH (n:test)
WITH collect(n.name) as nodes
WITH apoc.coll.zip(nodes, range(0, size(nodes))) as pairs
RETURN pairs;
--------------------------------
| pairs |
--------------------------------
| [["a", 0], ["b", 1], ["c", 2]] |
--------------------------------
Результат ожидаемый. Что интересно, так это когда я изменяю запрос либо путем добавления другого столбца в RETURN
предложение, либо путем UNWIND
добавления пары.
1. RETURN pairs,n.name;
MATCH (n:test)
WITH n, collect(n.name) as nodes
WITH n, apoc.coll.zip(nodes, range(0, size(nodes))) as pairs
RETURN pairs,n.name;
---------------------
| pairs | n.name |
---------------------
| [["a", 0]] | "a" |
| [["b", 0]] | "b" |
| [["c", 0]] | "c" |
---------------------
Я ожидаю, что результат будет точно таким же с запросом:
MATCH (n:test)
WITH n, [["a", 0], ["b", 1], ["c", 2]] as nested
RETURN nested, n.name;
---------------------––––––––––––––––––--
| pairs | n.name |
---------------------––––––––––––––––––--
| [["a", 0], ["b", 1], ["c", 2]] | "a" |
| [["a", 0], ["b", 1], ["c", 2]] | "b" |
| [["a", 0], ["b", 1], ["c", 2]] | "c" |
---------------------––––––––––––––––––--
2. UNWIND pairs as pair RETURN pairs
MATCH (n:test)
WITH n, collect(n.name) as nodes
WITH n, apoc.coll.zip(nodes, range(0, size(nodes))) as pairs
UNWIND pairs as pair
RETURN pairs;
------------
| pairs |
------------
| [["a", 0]] |
| [["b", 0]] |
| [["c", 0]] |
------------
Я ожидаю, что результат будет ничем не отличаться от отсутствия UNWIND
предложения:
--------------------------------
| pairs |
--------------------------------
| [["a", 0], ["b", 1], ["c", 2]] |
--------------------------------
3. UNWIND pairs as pair RETURN pair
MATCH (n:test)
WITH n, collect(n.name) as nodes
WITH n, apoc.coll.zip(nodes, range(0, size(nodes))) as pairs
UNWIND pairs as pair
RETURN pair;
----------
| pair |
----------
| ["a", 0] |
| ["b", 0] |
| ["c", 0] |
----------
Я ожидаю, что результат будет ничем не отличаться от простого UNWIND
вложенного списка:
UNWIND [["a", 0], ["b", 1], ["c", 2]] as list
RETURN list;
----------
| list |
----------
| ["a", 0] |
| ["b", 1] |
| ["c", 2] |
----------
Вы знаете, почему это происходит? Они, похоже, не объясняются в RETURN
документации и UNWIND
документации.
Ответ №1:
Для всех 3 перечисленных запросов ключевым моментом является,
...
WITH n, collect(n.name) as nodes
...
collect
является агрегирующей функцией, и ее можно сгруппировать. Указание «n» в WITH
предложении приводит к тому, что он выполняет «группировку по», аналогичную группировке SQL. Поэтому, если у вас есть 3 узла, вы получите 3 результата.
Вы можете выполнить отладку RETURN
, выполнив ее после WITH
, чтобы увидеть результат на каждом шаге, например так,
MATCH (n:test)
WITH n, collect(n.name) as nodes
RETURN n, nodes
Комментарии:
1. хмм. Итак, способ исправить это-создать специальное
WITH
предложение дляn
? Как только появитсяWITH
предложение для переменной, будет ли оно выдвинуто, даже если в другихWITH
предложениях его нет?2. один из упрощенных способов взглянуть на это-представить каждое предложение «WITH» как точку остановки в выполнении, где собираются промежуточные результаты, а затем отправляются в качестве входных данных в следующую часть инструкции cypher
3. да, но когда в следующей части будет другое
WITH
предложение, и мы больше не будем напоминать переменную, тогда она снова будет забыта?4. да, это так
5. но если это так, то как может сработать исправление?
n
будет забыто сразу послеWITH collect(n.name) as nodes