2015-12-28 2 views
1

Кто-нибудь знает быстрый способ запроса нескольких путей в Neo4j?Как запросить несколько путей OR'ed Neo4j?

Допустим, у меня есть узлы фильмов, которые могут иметь тип, который я хочу, чтобы соответствовать (это псевдо-код)

MATCH 
(m:Movie)<-[:TYPE]-(g:Genre { name:'action' }) 
OR 
(m:Movie)<-[:TYPE]-(x:Genre)<-[:G_TYPE*1..3]-(g:Genre { name:'action' }) 

(m)-[:SUBGENRE]->(sg:SubGenre {name: 'comedy'}) 
OR 
(m)-[:SUBGENRE]->(x)<-[:SUB_TYPE*1..3]-(sg:SubGenre {name: 'comedy'}) 

Проблема заключается в том, что первый «м: Фильм» узлы должны быть согласованы должны соответствуют одному из указанных путей, а второй SubGenre - в первом совпадении. Я могу сделать запрос, который работает с использованием MATCH и WHERE, но его очень медленный (30 секунд с небольшим набором данных 20 Мбайт).

Проблема в том, что я не знаю, как OR совпадать в Neo4j с другими совпадениями OR, зависящими от первых результатов.

Если я использую WHERE, то я должен объявить все узлы, используемые в каких-либо заявлений, в начальном MATCH, который делает запрос медленно (так как вы не можете ввести новые узлы в WHERE)

Кто-нибудь знает элегантный способ решить это? Благодаря !

ответ

1

Вы можете попробовать переменный путь длиной с минимальной длиной 0:

MATCH 
(m:Movie)<-[:TYPE|:SUBGENRE*0..4]-(g) 
WHERE g:Genre and g.name = 'action' OR g:SubGenre and g.name='comedy' 

Для запроса использовать индекс, чтобы найти свой жанр/поджанр рекомендую запрос UNION, хотя.

MATCH 
(m:Movie)<-[:TYPE*0..4]-(g:Genre { name:'action' }) 
RETURN distinct m 
UNION 
(m:Movie)-[:SUBGENRE]->(x)<-[:SUB_TYPE*1..3]-(sg:SubGenre {name: 'comedy'}) 
RETURN distinct m 
+0

Sweet, просто использовал измененную версию вашего запроса, чтобы получить результаты в 250 мс! Спасибо ! Я люблю Neo4j !! –

1

Возможно, OPTIONAL MATCH clause может помочь здесь. OPTIONAL MATCH beavior похож на оператор MATCH, за исключением того, что вместо подхода к сопоставлению шаблонов «все или ничего» любые элементы шаблона, которые не соответствуют шаблону, определенному в инструкции, привязаны к нулевому значению.

Например, чтобы соответствовать на фильм, его жанр и возможный поджанра:

OPTIONAL MATCH (m:Movie)-[:IS_GENRE]->(g:Genre)<-[:IS_SUBGENRE]-(sub:Genre) 
WHERE m.title = "The Matrix" 
RETURN m, g, sub 

Это вернет узел фильма, жанр узел и, если он существует, то поджанр. Если нет суб-жанра, он вернет значение null для sub. Вы можете использовать пути переменной длины, как и выше, с OPTIONAL MATCH.

+0

Спасибо, Уильям. Я попробовал использовать опциональный матч, но это было медленным с запросами –

1

[Изменено]

Следующая MATCH положение должно быть эквивалентно вашим псевдокод. Существует также статья USING INDEX, которая предполагает, что у вас есть created an index по адресу :SubGenre(name), для обеспечения эффективности. (Вы можете использовать индекс :Genre(name) вместо этого, если Genre узлов являются более многочисленными, чем SubGenre узлов.)

MATCH 
    (m:Movie)<-[:TYPE*0..4]-(g:Genre { name:'action' }), 
    (m)-[:SUBGENRE]->()<-[:SUB_TYPE*0..3]-(sg:SubGenre { name: 'comedy' }) 
USING INDEX sg:SubGenre(name) 

Here is a console, который показывает результаты для некоторых выборочных данных.

+0

Ваш запрос не содержит трудную часть, я пытался сопоставить Cypher ниже, если отношение переменной длины не существует: '(m: Movie) <- [: TYPE] - (g: Genre {name: 'action'}) ' –

+0

Обновлен мой ответ, чтобы исправить опечатку. Теперь он должен охватить это. – cybersam

+0

На самом деле, мой первоначальный ответ уже рассмотрел это, но обновленный ответ проще.Пример данных в моей связанной консоли содержит пример этого. – cybersam

Смежные вопросы