Neo4j MATCH затем MERGE слишком много попаданий в БД
Это запрос:
MATCH (n:Client{curp:'SOME_VALUE'})
WITH n
MATCH (n)-[:HIZO]-()-[r:FB]-()-[:HIZO]-(m:Client)
WHERE ID(n)<>ID(m)
AND NOT (m)-[:FB]->(n)
MERGE (n)-[:FB]->(m) RETURN m.curp
Почему на этапе слияния получается так много обращений к БД, если запрос уже сузил n, m пар до 6 781 строк?
Детали этого этапа показывают это:
n, m, r
(n)-[ UNNAMED155:FB]->(m)
1 ответ
Имейте в виду, что запросы формируют строки, и операции в вашем запросе выполняются на каждой построенной строке.
Поскольку шаблон в вашем совпадении может найти несколько путей к одному и тому же клиенту, он будет создавать несколько строк с одинаковыми n и m (но, возможно, с разными r, но, поскольку вы не используете r в другом месте в своем запросе, я призываю вам удалить переменную).
Это означает, что даже если вы хотите MERGE единственную связь между n и отдельным m, эта операция MERGE будет фактически выполняться для каждой повторяющейся строки n и m. Один из этих MERGE будет создавать отношения, другие будут тратить циклы, соответствующие отношениям, которые были созданы, не делая ничего больше.
Вот почему мы должны быть в состоянии снизить наши попадания в дб, рассматривая только отдельные пары n и m перед выполнением MERGE.
Кроме того, так как ваш запрос убедился, что мы рассматриваем только n и m, где отношения не существуют, мы можем безопасно использовать CREATE вместо MERGE, и это должно сэкономить нам несколько ударов в db, потому что MERGE всегда сначала пытается выполнить MATCH, что не не нужно
Улучшенный запрос может выглядеть так:
MATCH (n:Client{curp:'SOME_VALUE'})
WITH n
MATCH (n)-[:HIZO]-()-[:FB]-()-[:HIZO]-(m:Client)
WHERE n <> m
AND NOT (m)-[:FB]->(n)
WITH DISTINCT n, m
MERGE (n)-[:FB]->(m)
RETURN m.curp
РЕДАКТИРОВАТЬ
Возврат запроса для использования MERGE для отношения:FB, поскольку попытки использовать CREATE вместо этого закончились неудачей.