Монго агрегация: сортировка этап после поиска и раскрутка слишком медленно - PullRequest
0 голосов
/ 02 марта 2019

У меня есть коллекция, которая имеет около 30 атрибутов, 2 из которых являются отношениями (ObjectId) с 2 другими коллекциями.Мне нужно иметь возможность сортировать родительскую коллекцию по столбцам 2 дочерних коллекций.

Для этого я написал конвейер, который выглядит следующим образом:

 Document.aggregate([
  {
    $match: {
      deleted: false,
    },
  },
  {
    $lookup:
    {
      from: 'companies',
      localField: 'company',
      foreignField: '_id',
      as: 'company',
    },
  },
  {
    $unwind:
    {
      path: '$company',
      preserveNullAndEmptyArrays: true,
    },
  },
  {
    $lookup:
    {
      from: 'suppliers',
      localField: 'supplier',
      foreignField: '_id',
      as: 'supplier',
    },
  },
  {
    $unwind:
    {
      path: '$supplier',
      preserveNullAndEmptyArrays: true,
    },
  },
  {
    $sort: { 'company.name': -1 },
  },
  {
    $skip: 0,
  },
  {
    $limit: 10,
  }
]);

Проблема в том, что это слишком медленно.В Compass он превышает ограничение по времени, и когда я запускаю его в узле, обработка занимает около 10 секунд.Размер родительской коллекции составляет около 60К.Без этапа сортировки он работает около 25 мс.Кроме того, когда я перемещаю этап сортировки в верхнюю часть конвейера, он работает очень быстро, но результаты не будут правильными, если я хочу отсортировать по атрибуту company.name.Атрибуты «company» и «supplier» в родительской коллекции индексируются.

Я читал, что для того, чтобы на этапе сортировки использовались индексы, его нужно поместить в начало конвейера вместе со стадией 'match', но это не соответствует моему требованиюсортировка по атрибуту дочерней коллекции.Разве это невозможно сделать менее чем за 100 мс?Чего мне не хватает?

РЕДАКТ. 1

Вот объяснение:

{ stages:
   [ { '$cursor':
        { query: { state: true },
          queryPlanner:
           { plannerVersion: 1,
             namespace: 'test.documents',
             indexFilterSet: false,
             parsedQuery: { state: { '$eq': true } },
             winningPlan:
              { stage: 'FETCH',
                inputStage:
                 { stage: 'IXSCAN',
                   keyPattern: { state: 1 },
                   indexName: 'state_1',
                   isMultiKey: false,
                   multiKeyPaths: { state: [] },
                   isUnique: false,
                   isSparse: false,
                   isPartial: false,
                   indexVersion: 2,
                   direction: 'forward',
                   indexBounds: { state: [ '[true, true]' ] } } },
             rejectedPlans: [] } } },
     { '$lookup':
        { from: 'companies',
          as: 'company',
          localField: 'company',
          foreignField: '_id',
          unwinding: { preserveNullAndEmptyArrays: true } } },
     { '$lookup':
        { from: 'suppliers',
          as: 'supplier',
          localField: 'supplier',
          foreignField: '_id',
          unwinding: { preserveNullAndEmptyArrays: true } } },
     { '$sort': { sortKey: { 'company.name': -1 }, limit: 10 } } ],
  ok: 1 }

В коллекции документов company, supplier, state все поля являются индексами.

...