Cypher COLLECT заставляет UNWIND раскручиваться в неправильном порядке

Суть графика: http://gist.neo4j.org/?6182d024325343760cb4

Я хочу получить (самый длинный) путь по порядку, и он будет работать, как и ожидалось, до тех пор, пока я не добавлю инструкцию COLLECT, есть ли что-то, касающееся Cypher и COLLECT, которое я просто не понимаю, или это ошибка?

Этот запрос работает, как и ожидалось, возвращает узлы в пути в правильном порядке:

MATCH (n:Cable { name: 'Cable3' })-[:Connected_to*]-(port:Port)
OPTIONAL MATCH path=(port)-[:Connected_to*]-()
WITH nodes(path) AS parts, length(path) AS len
ORDER BY len DESC 
LIMIT 1 UNWIND parts AS part
RETURN part

Этот, без оператора COLLECT, возвращает узлы в правильном порядке, а также узлы между деталью и родителем (как и ожидалось).

MATCH (n:Cable { name: 'Cable3' })-[:Connected_to*]-(port:Port)
OPTIONAL MATCH path=(port)-[:Connected_to*]-()
WITH nodes(path) AS parts, length(path) AS len
ORDER BY len DESC
LIMIT 1 UNWIND parts AS part
OPTIONAL MATCH (part)<-[:Has*1..10]-(parent)
RETURN part, parent

Этот запрос не работает должным образом, возвращает узлы в пути в другом порядке:

MATCH (n:Cable { name: 'Cable3' })-[:Connected_to*]-(port:Port)
OPTIONAL MATCH path=(port)-[:Connected_to*]-()
WITH nodes(path) AS parts, length(path) AS len
ORDER BY len DESC
LIMIT 1 UNWIND parts AS part
OPTIONAL MATCH (part)<-[:Has*1..10]-(parent)
RETURN part, LAST(COLLECT(parent))

Любое понимание будет оценено.

1 ответ

Решение

UNWIND на самом деле все еще возвращает строки в ожидаемом порядке. Вместо этого это функция агрегирования, COLLECT()то есть "переставляет" результирующие строки. neo4j не гарантирует, что результирующие строки функции агрегирования будут в каком-либо конкретном порядке (без ORDER BY пункт).

Вот обходной путь, который избегает использования агрегации. Это может работать для вашего конкретного случая использования, в зависимости от ваших требований. Этот запрос фильтрует второй OPTIONAL MATCH так что он содержит максимально длинную последовательность Has отношения (до тех пор, пока самая длинная последовательность <= 10 прыжков - вы должны скорректировать это по мере необходимости или рассмотреть возможность устранения максимума). Запрос просто возвращает самого удаленного "предка" в каждой строке результата, и строки останутся в том порядке, который вы ожидаете.

MATCH (n:Cable { name: 'Cable3' })-[:Connected_to*]-(port:Port)
OPTIONAL MATCH path=(port)-[:Connected_to*]-()
WITH nodes(path) AS parts, length(path) AS len
ORDER BY len DESC 
LIMIT 1 UNWIND parts AS part
OPTIONAL MATCH (part)<-[:Has*1..10]-(ancestor)
WHERE NOT (ancestor)<-[:Has]-()
RETURN part, ancestor;
Другие вопросы по тегам