2016-08-16 2 views
0

Предполагая, что у меня есть Neo4j график природы:Как улучшить производительность двух сцепленных агрегатов в Neo4j запросе

enter image description here

create (SK:Author {name:'Stephen King'}), (JK:Author {name:'J.K. Rowling'}), (DS:Author {name:'Dr. Seuss'}), (TS:Book {name:'The Stand'}), (HP:Book {name:'Harry Potter'}), (CH:Book {name:'Cat in the Hat'}), (SHINING:Book {name:'The Shining'}), (PAF:Genre {name:'Post-Apocalyptic fiction'}), (F:Genre {name:'Fantasy'}), (C:Genre {name:'Childrens'}), (HORROR:Genre {name:'Horror'}), (SK)<-[:WRITTEN_BY]-(TS)-[:CATEGORIZED_AS]->(PAF), (JK)<-[:WRITTEN_BY]-(HP)-[:CATEGORIZED_AS]->(F), (DS)<-[:WRITTEN_BY]-(CH)-[:CATEGORIZED_AS]->(C), (SK)<-[:WRITTEN_BY]-(SHINING)-[:CATEGORIZED_AS]->(HORROR) 

Neo4j консоль ссылка: http://console.neo4j.org/r/2d69kq

У меня есть около 53000 автора узлов, 6 миллионов книжных узлов и 9 000 жанровых узлов.

Для запроса, как:

match (b:Book)-[:WRITTEN_BY]->(a:Author) 
where a.name in ['Stephen King', 'J.K. Rowling'] 
with a, collect(b) as bs 
unwind bs as book 
match (g:Genre)<-[r:CATEGORIZED_AS]-(book) 
where id(g) in [13, 14, 15, 16] 
with a, count(distinct book) as book_count_author, collect(book) as bs 
unwind bs as book 
match (g:Genre)<-[r:CATEGORIZED_AS]-(book) 
where id(g) in [13, 14, 15, 16] 
return a.name, g.name, count(distinct book) as book_count_genre, book_count_author 

Это занимает примерно 12 секунд. Я попытался переписать запрос несколькими различными способами и использовать подсказки индексов, но не могу понять, как это сделать быстрее. Есть предположения? Очевидно, этот пример упрощен, но у меня есть указатели на соответствующие свойства.

Вот пример результат из сцепленных агрегатов: enter image description here

мне нужно два скопления. Первый - это количество книг авторов, ограниченное указанными жанрами во втором матче. Второй подсчет книг по каждому автору в каждом жанре, опять же ограничен одним и тем же жанром.

+0

Ваши идентификаторы не переносятся для тех из нас, кто пытается воссоздать это в наших собственных системах (внутренние идентификаторы neo4j никогда не должны использоваться снаружи, поскольку они могут меняться, и идентификаторы могут повторно использоваться системой). Измените свой запрос, чтобы не использовать идентификаторы для соответствия. – InverseFalcon

+0

Можете ли вы также показать свою схему для индексов и ограничений? – InverseFalcon

+0

Re: Иды, вы можете использовать связанную консоль neo4j, которая должна содержать идентификаторы. Это не моя реальная схема, но представительная. Я не могу поделиться реальной схемой. У меня есть индексы для используемых столбцов и не вижу никаких сканирований в профиле выполнения. – David

ответ

0

Если предположить, что у вас есть индекс (или существование ограничений) на: Author.name, вы, вероятно, может использовать это:

match (book:Book)-[:WRITTEN_BY]->(a:Author) 
where a.name in ['Stephen King', 'J.K. Rowling'] 
with a, book 
match (g:Genre)<-[:CATEGORIZED_AS]-(book) 
return a, g, size((g)<-[:CATEGORIZED_AS]-()) as book_count_genre, count(book) as book_count_author 

Сбор и размотки может быть дорогим, старайтесь избегать его, где вы можете. Обратите внимание, что вы можете найти размер шаблона, чтобы получить счет шаблона, который в противном случае не был бы восстановлен путем подсчета на узле с учетом ваших столбцов.

EDIT

Модифицированного запрос для осветленных требований

book_count_genre - количество книг с этим жанром любого автором

book_count_author - количество книг с этим жанром, написанного данным автором

+0

Не уверен, что это работает, поскольку мне нужно, чтобы book_count_author ограничивался шаблоном (Жанр) <- [: CATEGORIZED_AS] - (книга). – David

+0

Возможно, вы можете добавить к своему описанию именно то, что вы хотите, и как оно должно быть ограничено. Запрос может показывать только то, что вы пробовали, но может быть не в состоянии полностью зафиксировать намерение. – InverseFalcon

+0

Вы правы, извините, я отредактировал описание, чтобы описать 2 числа, которые мне нужны. Оба счета должны быть ограничены указанными авторами и жанрами. – David

0

Что @InverseFalcon сказал.

Вы можете оптимизировать его немного дальше:

MATCH (g:Genre)<-[r:CATEGORIZED_AS]-(book:Book)-[:WRITTEN_BY]->(a:Author) 
WHERE a.name in ['Stephen King', 'J.K. Rowling'] 
    AND g.name IN ['Post-Apocalyptic fiction','Childrens','Horror','Fantasy'] 
WITH a, g, count(distinct book) as book_count_author_genre 
RETURN a.name, collect({ genre: g.name, count: book_count_author_genre}), 
     sum(book_count_author_genre) as book_count_author 

Вам может понадобиться использовать индекс-подсказки для авторов и жанров

Если вы используете идентификаторы для Lookup это будет быстрее.

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