2015-05-11 3 views
1

У меня есть этот запрос, возвращающийся очень быстро, 0,5 секунды и возвращающий все 303 ожидаемых отчета. Примечание: «Вока» здесь означает «Книга».Neo4j - не знаю, как улучшить запрос cypher

MATCH (p:Publisher)-[r:PUBLISHED]->(w:Woka)<-[s:AUTHORED]-(a:Author), 
(l:Language)-[t:USED]->(w:Woka)-[u:INCLUDED]->(b:Bisac) 
WHERE (a.author_name = 'Camus, Albert') 
RETURN w.woka_id as woka_id, p.publisher_name as publisher_name, w.woka_title as woka_title, a.author_name as author_name, l.language_name as language_name, b.bisac_code as bisac_code, b.bisac_value as bisac_value 
ORDER BY woka_id; 

И я хочу добавить дополнительную информацию, например, описание. У меня есть созданные узлы описания и созданные отношения, между языком и описанием, описанием и книгой (Woka). В нижеприведенном запросе все описания указаны как null, но только для 60 записей вместо 303. Это связано с тем, что не все книги имеют описание. Время выполнения все еще в порядке, 0,3 секунды.

MATCH (p:Publisher)-[r:PUBLISHED]->(w:Woka)<-[s:AUTHORED]-(a:Author), 
(l:Language)-[t:USED]->(w:Woka), (b:Bisac)<-[u:INCLUDED]-(w:Woka), 
(d:Description)-[v:HAS_DESCRIPTION]-(w) 
WHERE (a.author_name = 'Camus, Albert') 
RETURN w.woka_id as woka_id, p.publisher_name as publisher_name, w.woka_title as woka_title, a.author_name as author_name, l.language_name as language_name, b.bisac_code as bisac_code, b.bisac_value as bisac_value, d.description as description 
ORDER BY woka_id; 

Однако я знаю, что некоторые из записей исключены из набора результатов, разница между 50 и 303 действительно есть описание. Я создаю другой запрос, используя OPTIONAL, но этот (показанный ниже) никогда не возвращается, работает навсегда.

MATCH (p:Publisher)-[r:PUBLISHED]->(w:Woka)<-[s:AUTHORED]-(a:Author), 
(l:Language)-[t:USED]->(w:Woka)-[u:INCLUDED]->(b:Bisac) 
OPTIONAL MATCH (d:Description)-[v:HAS_DESCRIPTION]-(w:Woka)-[:AUTHORED]-(a:Author) 
WHERE (a.author_name = 'Camus, Albert') 
RETURN w.woka_id as woka_id, p.publisher_name as publisher_name, w.woka_title as woka_title, a.author_name as author_name, l.language_name as language_name, b.bisac_code as bisac_code, b.bisac_value as bisac_value, d.description as description 
ORDER BY woka_id; 

Не знаю, как улучшить запрос, чтобы получить дополнительные описания, где существует и аннулирует, когда они не существует для первоначального набора результатов 303 записей?

+0

Почему вы используете версию? –

ответ

2

Не могли бы вы попробовать это?

MATCH (p:Publisher)-[r:PUBLISHED]->(w:Woka)<-[s:AUTHORED]-(a:Author), (l:Language)-[t:USED]->(w)-[u:INCLUDED]->(b:Bisac) 
WHERE (a.author_name = 'Camus, Albert') 
WITH p,r,w,s,a,l,t,u,b 
OPTIONAL MATCH (d:Description)-[v:HAS_DESCRIPTION]-(w) 
RETURN w.woka_id as woka_id, p.publisher_name as publisher_name, w.woka_title as woka_title, a.author_name as author_name, l.language_name as language_name, b.bisac_code as bisac_code, b.bisac_value as bisac_value, d.description as description 
ORDER BY woka_id; 
+1

Я бы подтянул 'WHERE' до' WITH'. –

+0

Вы правы. Я отредактирую. – pablosaraiva

+0

Отредактированная версия работала, возвращая 303 строки за 0,5 секунды. Предыдущий никогда не возвращался. Однако одна из этих 303 строк должна иметь описание, отличное от нуля, но строка результата имеет нулевое описание. Это происходит для woka_id = '97818691945290000000' Маленький запрос, показывающий, что для этого описание не является нулевым: MATCH (d: Описание) - [: HAS_DESCRIPTION] - (w: Woka) - [: AUTHORED] - (: Автор), (l: Язык) - [: USED] - (w) - [: PUBLISHED] - (p: Publisher), (b: Bisac) - [: INCLUDED] - (w) где (d.woka_id = '97818691945290000000 ') return d, w, a, l, p, b; – LDB

5

Я думаю, что у нас уже был этот разговор некоторое время назад.

вы должны получить вниз вашу промежуточную кардинальность

направления использования в ваших отношениях

не повторять модели, которые вы уже решили, как

OPTIONAL MATCH (d:Description)-[v:HAS_DESCRIPTION]-(w:Woka)-[:AUTHORED]-(a:Author) 

должно быть

OPTIONAL MATCH (d:Description)-[v:HAS_DESCRIPTION]-(w) 

Если соответствующие длинные пути создания много потенциальных матчей между ними, для каждого этих строк следующий матч (а) выполняются, и если они создают несколько строк каждого вы получаете умножение rows1*rows2*rows3

Таким образом, вы должны использовать либо DISTINCT, либо агрегацию между ними, чтобы максимально увеличить мощность.

Просто продемонстрируйте его для вашего первого примера, один раз с DISTINCT, один раз с collect. Здесь может не понадобиться, но это просто для демонстрации, так как пример достаточно мал.

MATCH (p:Publisher)-[r:PUBLISHED]->(w:Woka)<-[s:AUTHORED]-(a:Author) 
WHERE (a.author_name = 'Camus, Albert') 
WITH DISTINCT w,a,p 

MATCH (l:Language)-[t:USED]->(w) 
WITH w,a,p, collect(l) as languages 

MATCH (w)-[u:INCLUDED]->(b:Bisac) 
RETURN w.woka_id as woka_id, w.woka_title as woka_title, 
     p.publisher_name as publisher_name, 
     a.author_name as author_name, 
     [l in languages | l.language_name] as language_names, 
     b.bisac_code as bisac_code, b.bisac_value as bisac_value 
ORDER BY woka_id; 

Вы правильно использовать OPTIONAL MATCH, но там снова, вы должны принять во внимание, что потенциальные дополнительные строки-отсчеты multiplicated в.

Альтернативный вариант для ФАКУЛЬТАТИВНЫМ MATCH является использование выражения пути и деконструкции, например,для описания:

RETURN w.woka_id as woka_id, w.woka_title as woka_title, 
     [p in()<-[:HAS_DESCRIPTION]-(w) | head(nodes(p)).description] as descriptions 
+0

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

3

В дополнение к @ pablosaraiva отношении ответа убедитесь, что у вас есть индекс: Автор и собственности author_name:

create index on :Author(author_name) 

Если это и ответ Пабло не помочь, пожалуйста, напишите запрос план вашего запроса. Используйте для этого explain <myquery> (при условии, что вы на> = 2.2)

+2

Уже проиндексирован. ON: Author (author_name) ONLINE (для ограничения уникальности) – LDB

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