2013-02-28 8 views
1

Что я делаю, чтобы получить все профилей *, который имеет специфическое направленное отношение к профилю пользователя * и, если таковым имеет другой профиль * получить те в случае, пользователей альтернативный профиль * имеет отношение к нему. Мне также нужно направление отношений.Оптимизировать Neo4j Cypher запрос

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

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

User - [: профиль] -> ProfileA - [: связанные с] -> ProfileB < - [?: меня] -> ProfileB2 < - [?: связанные с] -ProfileA2 < - [: профиль] -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

ответ

1

Это, как я ее решил:

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 казалось производить бесконечный цикл.

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

6

Вы используете WHERE статьи, в которых вам не нужно. Давайте посмотрим на первый, например:

WHERE User-->ProfileA-->ProfileB 

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

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 

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

+0

Проблема с вашим запросом заключается в том, что я получаю дубликаты. Между каждым узлом должен быть только один прыжок, и, насколько я понимаю, Neo4j жадный, если вы не укажете [: profile * .. 1], но это не будет работать с необязательными отношениями, поэтому мне нужно WHERE. – webjay

+0

Отношения [: me] символизируют ваш профиль Twitter, связанный с вашим профилем GitHub. – webjay

+0

Вот пример: http://console.neo4j.org/r/3hjktv, сделанный 'CREATE (Пользователь), (UserProfileA), (UserProfileB), (ProfileA), (ProfileB), Пользователь - [: profile] - > UserProfileA - [: follow] -> ProfileA - [: me] -> ПрофильB, ProfileA - [: follow] -> UserProfileA, Пользователь - [: profile] -> UserProfileB - [: follow] -> ProfileB- [ : me] -> ProfileA, ПрофильB - [: follow] -> UserProfileB; ' – webjay