#neo4j #cypher
#neo4j #cypher
Вопрос:
Использование http://console.neo4j.org как песочница, я столкнулся со следующим неожиданным поведением:
Оператор 1 — возвращает 1 строку с коллекцией, содержащей узел Neo
MATCH (n:Crew)
WHERE n.name="Neo"
WITH COLLECT(n) AS c1
WITH c1 [] AS c2
RETURN c2
Оператор 2 — возвращает 0 строк (неожиданно)
MATCH (n:Crew)
WHERE n.name="Neo"
WITH COLLECT(n) AS c1
MATCH (n:Crew)
WHERE n.name="NoOne"
WITH c1 COLLECT(n) AS c2
RETURN c2
Оператор 3 — возвращает 1 строку, содержащую пустую коллекцию
MATCH (n:Crew)
WHERE n.name="NoOne"
WITH COLLECT(n) AS c1
RETURN c1
Я не понимаю, почему оператор 2 не возвращает тот же результат, что и оператор 1, потому что он должен возвращать коллекцию, содержащую узел Neo, как и в инструкции 1.
Утверждение 3 показывает, что второе MATCH
в утверждении 2 должно приводить к пустой коллекции.
Ожидается ли такое поведение в Cypher? Если это так, я был бы рад небольшому объяснению, которое поможет мне понять это поведение.
Комментарии:
1. Используйте необязательное совпадение в инструкции 2, если СОВПАДЕНИЕ не возвращает данных, тогда (за исключением случаев, когда у вас есть ТОЛЬКО результат агрегирования) оно не вернет строк
Ответ №1:
Я уже сталкивался с таким точным поведением раньше, и это очень расстраивает. Проблема связана со вторым MATCH
предложением в запросе 2: если существующая строка результатов (в данном случае ваша единственная строка с c1
) не возвращает никаких результатов для a MATCH
, эта строка будет полностью удалена после этого MATCH
предложения, даже если MATCH
она сама по себе (без ранее существовавшей строки результатов) возвращаетпустая коллекция. Если вы преобразуете его в an OPTIONAL MATCH
, вы сможете сохранить свою результирующую строку, когда совпадений нет.
ОБНОВЛЕНИЕ: смотрите Ниже для более тщательного анализа, но tl, dr заключается в том, что второе COLLECT(n)
предложение в инструкции 2 возвращает пустой список, как и в инструкции 3; однако целое предложение WITH c1 COLLECT(n) AS c2
не возвращает строк, потому что после второго нет строк со c1
значением MATCH
.
Комментарии:
1. Однако, если от кого-то из Neo нет комментариев, я бы предложил поднять вопрос на GitHub . Это действительно похоже на непоследовательное поведение в отношении агрегаций.
2. Однако я не думаю, что это непоследовательное поведение агрегации; если вы удалите второй
c1
оператор from запроса 2WITH
, вы снова получите одну строку с пустой коллекцией.WITH
Инструкция , написанная в запросе 2, требует строки соc1
значением для создания новой результирующей строки, из которых она имеет 0, тогда как запрос 3 никогда не требует существующей результирующей строки.3. И если вы удалите промежуточное
WITH
звено (так что просто сложите дваMATCH
оператора, а затем выполните обаCOLLECTS
в одномWITH statement
), вы получите один пустой список (поскольку ни одна строка не будет соответствовать обоимMATCH
эс). Таким образом, поведение агрегации является самосогласованным,WITH
именно это вызывает проблему здесь.
Ответ №2:
Я не могу придумать правильного объяснения того, почему 2-й запрос не выполняет то, что вы ожидаете, но если у вас есть несколько необязательных совпадений, которые вы хотите объединить, вы можете использовать для этого НЕОБЯЗАТЕЛЬНОЕ СОВПАДЕНИЕ:
OPTIONAL MATCH (n:Crew)
WHERE n.name="Neo"
WITH COLLECT(n) AS c1
OPTIONAL MATCH (n:Crew)
WHERE n.name="NoOne"
WITH c1 COLLECT(n) AS c2
RETURN c2