Как получить доступ к общему количеству документов во время выражения арифметического агрегирования

У меня есть коллекция документов в этом формате:

{
    _id: ObjectId,
    items: [
        {
            defindex: number,
            ...
        },
        ...
    ]
}

Некоторые нерелевантные части схемы опущены, и каждый элемент defindex в массиве элементов гарантированно уникален для этого массива. Один и тот же defindex может встречаться в полях items разных документов, но будет встречаться только один раз в каждом соответствующем массиве, если он присутствует.

В настоящее время я вызываю $расслабиться для поля items, а затем $ sortByCount для items.defindex, чтобы получить отсортированный список элементов с наибольшим количеством.

Теперь я хочу добавить новое поле в этот окончательный отсортированный список, используя $установить, с именем usage, которое показывает использование элемента в процентах от начального количества всех документов в коллекции. (т. е. если count элемента равно 1300, а общее количество документов до $расслабиться составляло 2600, значение использования будет равно 0,5)

Мой первоначальный план состоял в том, чтобы использовать $фасет при первоначальной коллекции, создав документ следующим образом:

{
    total: number (achieved using $count),
    documents: [{...}] (achieved using an empty $set)
}

А затем вызов $расслабиться в поле документов, чтобы добавить общее количество документов к каждому документу. Вычисление значения использования затем тривиально с использованием $установить, поскольку общее количество является полем в самом документе.

Однако этот подход столкнулся с проблемами памяти, поскольку моя коллекция намного превышает ограничение в 16 МБ.

Как бы я решил это?

Что такое «общий размер коллекции до $unwind»? Не могли бы вы привести пример того, как это определяется?

rickhg12hs 05.04.2022 02:17

«Каждый элемент defindex в массиве элементов будет встречаться только один раз в этом массиве»? Что это значит? Во всем массиве "items" документа только один объект будет содержать поле "defindex"? Или каждое значение "defindex" гарантированно будет уникальным в пределах массива? Возможно, было бы полезно показать полный документ и продемонстрировать расчеты и желаемый результат.

rickhg12hs 05.04.2022 02:27

@rickhg12hs извините за неясность! Под «общим размером коллекции до раскрутки» я имел в виду общее количество исходных документов в коллекции до выполнения какой-либо агрегации. то есть результат $count. И с точки зрения «defindex» я имел в виду, что каждое значение (если оно присутствует) гарантированно будет уникальным в пределах массива. Разные документы могут содержать один и тот же defindex элемента, но он будет только один раз в соответствующих массивах.

Oli Fog 05.04.2022 13:22

Кстати, я решил эту проблему, не используя конвейеры агрегации данных и выполняя вычисления вручную с помощью машинописного текста. Однако я оставляю этот вопрос открытым, так как сделать это в конвейере было бы намного лучше (и кажется, что это должно быть довольно просто, я просто не мог понять это!)

Oli Fog 05.04.2022 13:24

Я думаю, начиная с: { $setWindowFields: { output: { totalCount: {$count: {}}}}} может работать на вас

nimrod serok 05.04.2022 14:22

@nimrodserok это прекрасно, большое спасибо! Если вы поместите это в ответ, я приму это. Я понятия не имел, что setWindowFields существует, это очень помогает

Oli Fog 05.04.2022 14:46
Использование JavaScript и MongoDB
Использование JavaScript и MongoDB
Сегодня я собираюсь вкратце рассказать о прототипах в JavaScript, а также представить и объяснить вам работу с базой данных MongoDB.
0
6
37
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Один из способов сделать это — использовать $setWindowFields:

db.collection.aggregate([
  {
    $setWindowFields: {
      output: {
        totalCount: {$count: {}}
      }
    }
  },
  {
    $unwind: "$items"
  },
  {
    $group: {
      _id: "$items.defindex",
      count: {$sum: 1},
      totalCount: {$first: "$totalCount"}
    }
  },
  {
    $project: {
      count: 1,
      usage: {$divide: ["$count", "$totalCount"]
      }
    }
  },
  {$sort: {count: -1}}
])

Как видите, здесь

Другие вопросы по теме