Neo4J Cypher Query для поиска общих связанных узлов - PullRequest
0 голосов
/ 08 июня 2018

Я делаю именованный граф сущностей в Noe4j 3.2.0.У меня есть ARTICLE и ENTITY в качестве типов узлов.И отношение / край между ними CONTAINS;который представляет количество раз, когда сущность встречалась в этой статье (как показано на прилагаемом рисунке Простой график для статей и сущностей ).Таким образом, если статья имеет одну сущность 5 раз, между этой статьей и конкретной сущностью будет 5 ребер.

Существует около 18 миллионов статей и 40 тысяч уникальных сущностей.Все данные составляют около 20 ГБ (включая индексы на идентификаторах) и загружаются на машину с 32 ГБ ОЗУ.

Я использую этот график, чтобы предлагать / рекомендовать другие организации.Но мои запросы занимают слишком много времени.

Вариант использования 1: Найти все сущности, присутствующие в статьях, которые имеют сущность из списка ["A", "B"], а также имеют сущность "X" и сущность "Y" и сущность "Z"."в порядке количества статей.

Вот запрос шифра, который я выполняю.

MATCH(e:Entity)-[:CONTAINS]-(a:Article)
WHERE e.EID in ["A","B"]
WITH a
MATCH (:Entity {EID:"X"})-[:CONTAINS]-(a)
WITH a
MATCH (:Entity {EID:"Y"})-[:CONTAINS]-(a)
WITH a
MATCH (:Entity {EID:"Z"})-[:CONTAINS]-(a)
WITH a
MATCH (a)-[:CONTAINS]-(e2:Entity)
RETURN e2.EID as EID, e2.Text as Text, e2.Type as Type ,count(distinct(a)) as articleCount
ORDER BY articleCount desc

Профиль запроса находится здесь: Профиль запроса

Этот запрос дает мне всех соседей сущности первого уровня статей, имеющих X, Y, Z и хотя бы один изОбъекты A, B (мне пришлось изменить идентификаторы в запросе на чувствительность содержимого).

Мне просто интересно, есть ли лучший / быстрый способ сделать это?

Другое замечание: если я продолжу добавлять фильтры (больше соответствий, таких как X, Y, Z), производительность ухудшится;несмотря на то, что набор результатов становится все меньше и меньше.

1 Ответ

0 голосов
/ 13 июня 2018

У вас есть ограничение уникальности для :Entity(EID), поэтому, по крайней мере, эта оптимизация уже на месте.

Следующий запрос Cypher является более простым и генерирует более простой план выполнения.Надеюсь, это также уменьшает количество обращений к БД.

MATCH (e:Entity)-[:CONTAINS]-(a)
WHERE e.EID in ['A','B'] AND ALL(x IN ['X','Y','Z'] WHERE (:Entity {EID: x})-[:CONTAINS]-(a))
WITH a
MATCH (a)-[:CONTAINS]-(e2:Entity)
RETURN e2.EID as EID, e2.Text as Text, e2.Type as Type, COUNT(DISTINCT a) as articleCount
ORDER BY articleCount DESC;
...