#neo4j #cypher
#neo4j #cypher
Вопрос:
Ниже приведена диаграмма, дающая вам общее представление о том, как структурирован мой график:
http://i.stack.imgur.com/hbn0J.png
Он просто содержит узлы :Person, которые присоединены к :PersonType. Каждый : Пользователь может выразить ноль или более мнений. Эти мнения являются либо подлинными мнениями (:Opinion), либо мнениями, заимствованными у кого-то другого (:OpinionProxy). An :OpinionProxy или an :Opinion всегда имеет одно и только одно: ВЫРАЖЕННОЕ отношение.
Я написал запрос cypher, чтобы ответить на следующий вопрос: дайте мне все мнения, высказанные всеми «Крутыми парнями», и для каждого мнения цепочку людей, через которых прошло это мнение.
Пример с образцом данных:
-------------------- --------------------- ---------------------
| person | opinion | influence |
-------------------- --------------------- ---------------------
| "Dan" | o4 | "Dan" |
-------------------- --------------------- ---------------------
| "Dan" | o3 | "Dan", "Jim", "Jay" |
-------------------- --------------------- ---------------------
| "Bob" | ... | ... |
-------------------- --------------------- ---------------------
Вот запрос, который ищет все мнения всех «крутых парней»:
MATCH
(:PersonType {name: "Cool Guys"})<-[:OF_TYPE]-(p:Person)-[:EXPRESSES]->(o),
opath=(o)-[:REFERENCES*0..]->(op:Opinion)
RETURN p.name AS person, op AS opinion, opath
Пока все хорошо. Теперь сложная часть возникает при попытке вернуть цепочку :Person, а не цепочку :OpinionProxy-[*0 ..]->:Мнение. Вот моя попытка:
MATCH
(:PersonType {name: "Cool Guys"})<-[:OF_TYPE]-(p:Person)-[:EXPRESSES]->(o),
opath=(o)-[:REFERENCES*0..]->(op:Opinion)
MATCH (x)<-[:EXPRESSES]-(opAuthor:Person)
WHERE x IN nodes(opath)
RETURN p.name AS person, op AS opinion, collect(opAuthor) AS influence
Этот запрос возвращает именно то, что я хочу, за исключением того, что он выполняется чрезвычайно медленно.
Чтобы дать вам представление, в моей тестовой среде у меня около 3000: Person (включая 70 «Крутых парней»), 3000: Opinion и 3000:OpinionProxy. Время отклика:
- Запрос 1: завершается примерно через 200 мс
- Запрос 2: завершается примерно через 3200 мс
Это на порядок больше, просто чтобы «присоединиться» к :Person, связанному с :Opinion или :OpinionProxy. Для Neo4j это всего лишь один указатель для следования, и я не ожидал увидеть такой разрыв в производительности между этими двумя запросами.
Что-то не так с моим вторым запросом? Как я могу это оптимизировать?
Ответ №1:
Вы можете попробовать использовать оператор WITH между двумя операторами match. Я думаю, что теперь первое СОВПАДЕНИЕ будет выполняться снова и снова.
MATCH
(:PersonType {name: "Cool Guys"})<-[:OF_TYPE]-(p:Person)-[:EXPRESSES]->(o),
opath=(o)-[:REFERENCES*0..]->(op:Opinion)
WITH opath,p,op
MATCH (x)<-[:EXPRESSES]-(opAuthor:Person)
WHERE x IN nodes(opath)
RETURN p.name AS person, op AS opinion, collect(opAuthor) AS influence
Комментарии:
1. Спасибо за ваш ответ. Хотя ваш запрос по-прежнему возвращает правильный набор данных, он выполняется одинаково медленно.
2. Можете ли вы сгенерировать план выполнения для вашего запроса? Запустите ваш запрос в neo4-shell с предварением «profile» следующим образом: соответствие профиля (:PersonType …
3. Вот профиль для исходного запроса и вашей версии: pastebin.com/x6T2A7MQ . Еще раз большое спасибо за изучение этого!