У меня есть коллекция документов в этом формате:
{
_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 МБ.
Как бы я решил это?
«Каждый элемент defindex в массиве элементов будет встречаться только один раз в этом массиве»? Что это значит? Во всем массиве "items"
документа только один объект будет содержать поле "defindex"
? Или каждое значение "defindex"
гарантированно будет уникальным в пределах массива? Возможно, было бы полезно показать полный документ и продемонстрировать расчеты и желаемый результат.
@rickhg12hs извините за неясность! Под «общим размером коллекции до раскрутки» я имел в виду общее количество исходных документов в коллекции до выполнения какой-либо агрегации. то есть результат $count. И с точки зрения «defindex» я имел в виду, что каждое значение (если оно присутствует) гарантированно будет уникальным в пределах массива. Разные документы могут содержать один и тот же defindex элемента, но он будет только один раз в соответствующих массивах.
Кстати, я решил эту проблему, не используя конвейеры агрегации данных и выполняя вычисления вручную с помощью машинописного текста. Однако я оставляю этот вопрос открытым, так как сделать это в конвейере было бы намного лучше (и кажется, что это должно быть довольно просто, я просто не мог понять это!)
Я думаю, начиная с: { $setWindowFields: { output: { totalCount: {$count: {}}}}}
может работать на вас
@nimrodserok это прекрасно, большое спасибо! Если вы поместите это в ответ, я приму это. Я понятия не имел, что setWindowFields существует, это очень помогает
Один из способов сделать это — использовать $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}}
])
Как видите, здесь
Что такое «общий размер коллекции до
$unwind
»? Не могли бы вы привести пример того, как это определяется?