В Mongo Aggregation можно сделать через временный массив.
1. Сортируем все документы в порядке убывания rating и active (позиция будет расти сверху вниз)
2.
$push всех отсортированных документов во временный массив
data
3. Создание нового массива
arr и внесение в него всех элементов массива
data в том же порядке, но добавляя поле
position, которое формируется исходя из положения объекта в массиве
data (
$indexOfArray)
4. Разбиение (
$unwind) массива
arr на обычный список документов, но уже отсортированный и с проставленными
position
5. Преобразование документов после разбиения к нужному виду
db.getCollection('testo').aggregate([
{ $sort: { rating: -1, active: -1 } },
{ $group: { _id: null, data: { $push: "$$ROOT" } } },
{
$project: {
arr: {
$map: {
input: "$data", as: "e", in: {
rating: "$$e.rating",
active: "$$e.active",
position: {
$add: [{ $indexOfArray: ["$data", "$$e"] }, 1]
}
}
}
}
}
},
{ $unwind: "$arr" },
{ $project: {
_id: 0,
rating: "$arr.rating",
active: "$arr.active",
position: "$arr.position" } }
])
Если версия MongoDB довольно старая, то придется вручную вписывать все поля, которые нужно учитывать в массиве. Если же версия новая, можно дополнить действием
$mergeObjects. Также есть вариант использовать более сложные схемы (
$arrayToObject,
$objectToArray) для сохранения полей при переходе массива из одного состояния в другое