Оптимизация запроса Neo4j Cypher

Что я делаю, так это получаю все профили*, ​​которые имеют конкретное направленное отношение к профилю пользователя*, ​​и если у них есть альтернативный профиль * получить их, если альтернативный профиль пользователя* имеет отношение к нему. Мне также нужно направление отношений.

Моя проблема в том, что при наличии около 10000 узлов получение данных занимает около 5 секунд. У меня есть автоматический индекс узлов и отношений.

Вот как связаны мои узлы:

Пользователь-[:profile]->ProfileA-[:related]->ProfileB‹-[?:me]->ProfileB2‹-[?:related]-ProfileA2‹-[:profile]-User

Мой запрос выглядит так:

START User=node({source}) 
MATCH User-[:profile]->ProfileA-[rel:related]->ProfileB 
WHERE User-->ProfileA-->ProfileB 
WITH ProfileA, rel, ProfileB 
MATCH ProfileB<-[?:me]->ProfileB2<-[relB?:related]-ProfileA2<-[:profile]-User 
WHERE relB IS NULL OR User-->ProfileA-->ProfileB<-->ProfileB2<--ProfileA2<--User
RETURN ProfileB, COLLECT(ProfileB2), rel, relB
LIMIT 25

Любая идея, как я могу оптимизировать запрос?


  • профили: ProfileB
  • профиль пользователя: ProfileA
  • альтернативный профиль: ProfileB2
  • альтернативный профиль пользователя: ProfileA2

person webjay    schedule 28.02.2013    source источник


Ответы (2)


Вы используете предложения WHERE там, где это не нужно. Рассмотрим, например, первый:

WHERE User-->ProfileA-->ProfileB 

В этом пункте говорится: «ограничить результаты только пользователями, имеющими отношение к ProfileA, который сам имеет отношение к ProfileB». Тем не менее, это уже гарантируется вашим условием соответствия. Вы тратите циклы ЦП на повторную проверку того, что уже верно.

WITH ProfileA, rel, ProfileB 

Вы не выполняете какую-либо агрегацию, вычисление или переназначение, поэтому в этом предложении WITH нет необходимости. Можно продолжать без него.

WHERE relB IS NULL OR User-->ProfileA-->ProfileB<-->ProfileB2<--ProfileA2<--User

Опять же, вы не получаете никакой пользы от этого пункта WHERE. В этом говорится: «ограничьте результаты путями, где relB не был найден ИЛИ где он был найден со следующим путем ...», а затем вы указываете точно такой же путь, который был в вашем MATCH.

Итак, удалите все эти посторонние предложения, и вы получите это:

START User=node({source}) 
MATCH User-[:profile]->ProfileA-[rel:related]->ProfileB<-[?:me]->ProfileB2<-[relB?:related]-ProfileA2<-[:profile]-User 
RETURN ProfileB, COLLECT(ProfileB2), rel, relB
LIMIT 25

Попробуйте это и посмотрите, улучшится ли производительность. Если этого недостаточно, вам, возможно, потребуется добавить дополнительную информацию к вашему вопросу — что касается меня, я не совсем понимаю, что на самом деле означают ваши отношения (например, что такое «я», отношения? что это символизирует?)

person ean5533    schedule 01.03.2013
comment
Проблема с вашим запросом в том, что я получаю дубликаты. Между каждым узлом должен быть только один переход, и, насколько я понимаю, Neo4j жадный, если вы не укажете [:profile*..1], но это не будет работать с необязательными отношениями, поэтому мне нужно ГДЕ. - person webjay; 01.03.2013
comment
Связь [:me] символизирует ваш профиль Twitter, связанный с вашим профилем GitHub. - person webjay; 01.03.2013
comment
Вот пример: console.neo4j.org/r/3hjktv, созданный CREATE (User), (UserProfileA), (UserProfileB), (ProfileA), (ProfileB), User-[:profile]->UserProfileA-[:follow]->ProfileA-[:me]->ProfileB, ProfileA-[:follow]->UserProfileA, User-[:profile]->UserProfileB-[:follow]->ProfileB-[:me]->ProfileA, ProfileB-[:follow]->UserProfileB; - person webjay; 03.03.2013
comment
@webjay Я не уверен, что вы имеете в виду под жадностью в своем первом комментарии. Он не будет проходить более чем на одну глубину, если вы не укажете :profile* или какой-либо вариант пути переменной длины. - person Eve Freeman; 03.03.2013
comment
Я думал, что Neo4j был жадным, поскольку руководство здесь указывает, что minHops и maxHops являются необязательными и по умолчанию равны 1 и бесконечности соответственно, но я думаю, что это только в том случае, если используется *. - person webjay; 03.03.2013

Вот как я это решил:

START User=node({source}) 
MATCH User-[:profile]->ProfileA-[rel:related]->ProfileB<-[?:me]->ProfileB2-[relB?:related]-ProfileA2
WHERE relB IS NULL OR User-[:profile]->ProfileA2
RETURN ProfileB, COLLECT(ProfileB2), rel, relB
LIMIT 25

ProfileA2<-[:profile]-User, казалось, создавал бесконечный цикл.

Рекомендации по-прежнему приветствуются.

person webjay    schedule 03.03.2013