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;