Оптимизировать запрос на шифрование, чтобы избежать декартового произведения.
Цель запроса довольно тривиальна. Для заданного nodeId(userId) я хочу вернуть на графике все узлы, которые имеют связь в пределах X прыжков, и я хочу агрегировать и вернуть расстояние (параметр, который устанавливается для отношения) между ними)
Я придумал это:
MATCH p=shortestPath((user:FOLLOWERS{userId:{1}})-[r:follow]-(f:FOLLOWERS)) " +
"WHERE f <> user " +
"RETURN (f.userId) as userId," +
"reduce(s = '', rel IN r | s + rel.dist + ',') as dist," +
"length(r) as hop"
ИД пользователя ({1}) указан как входной и индексируется.
Я верю, что у меня есть здесь декартово произведение. как бы вы предложили избегать этого?
1 ответ
Вы можете сделать декартово произведение менее обременительным, создав индекс на :FOLLOWERS(userId)
чтобы ускорить одну из двух "ножек" декартового произведения:
CREATE INDEX ON :FOLLOWERS(userId);
Даже если это не избавит от декартового произведения, оно будет работать за O(N log N), что намного быстрее, чем O(N ^ 2).
Кстати, ваш r
Чтобы ваш запрос работал, отношения должны быть переменной длины. Вы должны указать разумную верхнюю границу (которая зависит от вашей БД), чтобы гарантировать, что запрос завершится в разумные сроки и не исчерпает память. Например:
MATCH p=shortestPath((user:FOLLOWERS { userId: 1 })-[r:follow*..5]-(f:FOLLOWERS))
WHERE f <> user
RETURN (f.userId) AS userId,
REDUCE (s = '', rel IN r | s + rel.dist + ',') AS dist,
LENGTH(r) AS hop;