Сайфер для поиска и упорядочения по нескольким значениям - PullRequest
0 голосов
/ 04 мая 2020

У меня есть JSON документ с историей, основанной на количестве объектов и количестве отношений. Я хочу использовать эти данные поиска для сущности и отношений в Neo4j. Поиск данных имеет около 3000 строк. Для счетчиков объектов я хочу отобразить счетчики для двух объектов на основе UUID. Для отношений я хочу упорядочить по двум счетам отношений (связанные сущности и связанные взаимные сущности).

Для сущностей я начал со следующего:

// get JSON doc
with value.aggregations.ent.terms.buckets as data

unwind data as lookup1
unwind data as lookup2

MATCH (e1:Entity)-[r1:RELATED_TO]-(e2)
WHERE e1.uuid = '$entityId'
AND e1.uuid = lookup1.key
AND e2.uuid = lookup2.key
RETURN e1.uuid, lookup1.doc_count, r1.uuid, e2.uuid, lookup2.doc_count
ORDER BY lookup2.doc_count DESC  // just to demonstrate
LIMIT 50

Я заметил, что запрос занимает около 10 секунд. Что я делаю не так и как я могу это исправить?

Приложение плана объяснения:

enter image description here

1 Ответ

0 голосов
/ 05 мая 2020

Ваш запрос очень неэффективен. Вы заявили, что data имеет 3000 строк (назовем это число D).

  1. Итак, ваш первый UNWIND создает промежуточный результат из D строк.
  2. Ваш второй UNWIND создает промежуточный результат из D**2 (то есть, 9 миллионов) строк.
  3. Если ваше предложение MATCH (e1:Entity)-[r1:RELATED_TO]-(e2) находит N результатов, то генерируется промежуточный результат до N * (D ** 2) строки.
  4. Поскольку в предложении MATCH указан шаблон ненаправленного отношения, он находит одну и ту же пару узлов дважды (в обратном порядке). Итак, N на самом деле в два раза больше, чем нужно.

Вот улучшенная версия вашего запроса, которая должна быть намного быстрее (с N / 2 промежуточными строками):

WITH apoc.map.groupBy(value.aggregations.ent.terms.buckets, 'key') as lookup
MATCH (e1:Entity)-[r1:RELATED_TO]->(e2)
WHERE e1.uuid = $entityId AND lookup[e1.uuid] IS NOT NULL AND lookup[e2.uuid] IS NOT NULL
RETURN e1.uuid, lookup[e1.uuid].doc_count AS count1, r1.uuid, e2.uuid, lookup[e2.uuid].doc_count AS count2
ORDER BY count2 DESC
LIMIT 50

Хитрость в том, что запрос использует apo c .map.groupBy для преобразования вашего buckets (списка карт) в единую объединенную lookup карту, которая использует значения key в качестве имен своих свойств. Это позволяет остальной части запроса буквально «искать» данные uuid на объединенной карте.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...