Arhn - архитектура программирования

Neo4j - ОБЪЕДИНЕНИЕ 3 разных запросов

У меня проблема с одним составленным запросом, состоящим из трех частей.

  1. Получить прямых друзей
  2. Получить друзей друзей
  3. Получите другие - просто заполните пространство, чтобы ограничить

Таким образом, он всегда должен возвращать ограниченных пользователей, заказанных прямыми друзьями, друзьями друзей и другими. Первые две части очень быстрые, здесь нет проблем, но последняя часть медленная и становится все медленнее по мере увеличения размера db. Есть индексы на Person.number и Person.createdAt.

У кого-нибудь есть идея, как улучшить или переписать этот запрос, чтобы он был более производительным?

MATCH (me:Person { number: $number })-[r:KNOWS]-(contact:Person { registered: "true" }) WHERE contact.number <> $number AND (r.state = "contact" OR r.state = "declined")
    MATCH (contact)-[:HAS_AVATAR]-(avatar:Avatar { primary: true })
    WITH contact, avatar
    RETURN contact AS friend, avatar, contact.createdAt AS rank
    ORDER BY contact.createdAt DESC
  UNION
    MATCH (me:Person { number: $number })-[:KNOWS]-(friend)-[:KNOWS { state: "accepted" }]-(friend_of_friend:Person { registered: "true" }) WHERE NOT friend.username = 'default' AND NOT (me)-[:KNOWS]-(friend_of_friend)
    MATCH (friend_of_friend)-[:HAS_AVATAR]-(avatar:Avatar { primary: true })
    OPTIONAL MATCH (friend_of_friend)-[rel:KNOWS]-(friend)
    RETURN friend_of_friend AS friend, avatar, COUNT(rel) AS rank
    ORDER BY rank DESC
  UNION
    MATCH (me:Person { number: $number })
    MATCH (others:Person { registered: "true" }) WHERE others.number <> $number AND NOT (me)-[:KNOWS]-(others) AND NOT (me)-[:KNOWS]-()-[:KNOWS { state: "accepted" }]-(others:Person { registered: "true" })
    MATCH (others)-[:HAS_AVATAR]->(avatar:Avatar { primary: true })
    OPTIONAL MATCH (others)-[rel:KNOWS { state: "accepted" }]-()
    WITH others, rel, avatar
    RETURN others AS friend, avatar, COUNT(rel) AS rank
    ORDER BY others.createdAt DESC
  SKIP $skip
  LIMIT $limit

Вот некоторые профили:

https://i.stack.imgur.com/LfNww.png

https://i.stack.imgur.com/0EO0r.png

Окончательное решение состоит в том, чтобы разбить весь запрос на три и вызывать их по отдельности, в нашем случае он не достигнет третьего запроса в 99%, а первые два очень быстрые. И кажется, что даже если он достигает 3-й стадии, он все еще быстр, так что, возможно, UNION больше всего замедлял все это.

const contacts = await this.neo4j.readQuery(`...
if (contacts.records.length < limit){
  const friendOfFriend = await this.neo4j.readQuery(`...
  if (contacts.records.length + friendOfFriend.records.length < limit){
    const others = await this.neo4j.readQuery(`...

merge all results
02.08.2019

  • Можете ли вы запустить ПРОФИЛЬ по этому запросу, развернуть все элементы результирующего плана (кнопка с двойной стрелкой вниз в правом нижнем углу панели результатов) и добавить изображение к своему вопросу? 03.08.2019

Ответы:


1

Вы делаете много работы в этом третьем запросе до предела. Возможно, вы захотите переместить порядок и LIMIT раньше.

Также будет более эффективно выполнять предварительное сопоставление с друзьями (и друзьями друзей) в одном шаблоне ПОИСКПОЗ, мы можем использовать *0..1 в качестве необязательного отношения к потенциальному следующему узлу.

И небольшой совет по стилю: я считаю хорошей идеей зарезервировать множественное число для списков/коллекций и в противном случае использовать единственное число, так как у вас будет только один из этих узлов в строке.

Попробуйте это для третьей части:

  MATCH (me:Person { number: $number })
  OPTIONAL MATCH (me)-[:KNOWS]-()-[:KNOWS*0..1 { state: "accepted" }]-(other:Person {registered:"true"})
  WITH collect(DISTINCT other) as excluded
  MATCH (other:Person { registered: "true" }) WHERE other.createdAt < dateTime() AND other.number <> $number AND NOT other IN excluded
  WITH other
  ORDER BY other.createdAt DESC
  SKIP $skip
  LIMIT $limit
  MATCH (other)-[:HAS_AVATAR]->(avatar:Avatar { primary: true })
  WITH other, avatar, size((other)-[:KNOWS { state: "accepted" }]-()) AS rank
  RETURN other AS friend, avatar, rank

Если мы знаем тип createdAt, мы можем добавить модификацию, которая может вызвать упорядочение по индексу, что может улучшить это.

02.08.2019
  • createdAt is datetime Это немного улучшило производительность, но все равно очень медленно. 03.08.2019
  • Я только что добавил изменение в запрос, которое, как я ДУМАЮ, должно включать упорядочение на основе индекса. Попробуйте это и посмотрите, сможете ли вы получить ПРОФИЛЬ этого. 03.08.2019
  • Результат очень похож, добавил еще один профиль. 03.08.2019
  • Еще один вопрос, как мне добиться, чтобы от этих союзов было только 50 результатов, теперь я вижу гораздо больше результатов. Есть ли что-то вроде LIMIT на UNIONS? Потому что кажется, что ограничение применяется только к последнему запросу. 03.08.2019
  • Спасибо за подсказки, ведь я разбиваю этот запрос на три, вызывая их по отдельности и только при необходимости (если количество предыдущих результатов меньше лимита 50), вызывая следующий. Удивительно, но по статистике кажется, что 99% пользователей не достигнут фазы 3, и если это так, то это очень быстро. Так что, возможно, этот союз замедлял все это. 03.08.2019
  • К сожалению, обработка после объединения в настоящее время не поддерживается, поэтому любые LIMIT или другие операции могут повлиять только на данный подзапрос и не могут быть применены к объединенному результату. Тем не менее, есть несколько методов обработки после UNION, которые могут помочь ликвидировать разрыв. 05.08.2019
  • Новые материалы

    Коллекции публикаций по глубокому обучению
    Последние пару месяцев я создавал коллекции последних академических публикаций по различным подполям глубокого обучения в моем блоге https://amundtveit.com - эта публикация дает обзор 25..

    Представляем: Pepita
    Фреймворк JavaScript с открытым исходным кодом Я знаю, что недостатка в фреймворках JavaScript нет. Но я просто не мог остановиться. Я хотел написать что-то сам, со своими собственными..

    Советы по коду Laravel #2
    1-) Найти // You can specify the columns you need // in when you use the find method on a model User::find(‘id’, [‘email’,’name’]); // You can increment or decrement // a field in..

    Работа с временными рядами спутниковых изображений, часть 3 (аналитика данных)
    Анализ временных рядов спутниковых изображений для данных наблюдений за большой Землей (arXiv) Автор: Рольф Симоэс , Жильберто Камара , Жильберто Кейрос , Фелипе Соуза , Педро Р. Андраде ,..

    3 способа решить квадратное уравнение (3-й мой любимый) -
    1. Методом факторизации — 2. Используя квадратичную формулу — 3. Заполнив квадрат — Давайте поймем это, решив это простое уравнение: Мы пытаемся сделать LHS,..

    Создание VR-миров с A-Frame
    Виртуальная реальность (и дополненная реальность) стали главными модными терминами в образовательных технологиях. С недорогими VR-гарнитурами, такими как Google Cardboard , и использованием..

    Демистификация рекурсии
    КОДЕКС Демистификация рекурсии Упрощенная концепция ошеломляющей О чем весь этот шум? Рекурсия, кажется, единственная тема, от которой у каждого начинающего студента-информатика..