У меня есть коллекция MongoDB, в которой есть массив объектов, и я хочу добавить добавочное значение индекса к каждому элементу массива объектов.
Индекс лайка начинается с 0 до длины массива — 1. Данные :
db = "abc" : {
"array": [
{
"_id": "a",
"timestamp": "t1",
"type": "object"
}
]
}
db.collection.aggregate([
{
"$unwind": "$array"
},
{
"$addFields": {
"array.index": {
"$add": [
{
"$ifNull": ["$index", 0]
},
1
]
}
}
},
{
"$group": {
"_id": "$_id",
"array": {
"$push": "$$ROOT.array"
}
}
}
])

MongoDB playground link:https://mongoplayground.net/p/SWw7rIYHNcj
db.collection.aggregate([
{
"$unwind": {
"path": "$array",
"includeArrayIndex": "index"
}
},
{
"$addFields": {
"array.index": {
"$toInt": "$index"
}
}
},
{
"$group": {
"_id": "$_id",
"array": {
"$push": "$$ROOT.array"
}
}
}
])
$unwind stage:
Открывает поле массива ($array) из входных документов.
Создает новый документ для каждого элемента массива.
Включает индекс массива каждого элемента в новое поле с помощью includeArrayIndex.
$addFields stage:
Добавляет новое поле («array.index») в каждый документ.
Преобразует поле «index» в целое число с помощью оператора $toInt.
$group stage:
Группирует документы по полю «_id».
Создает поле «массив» внутри каждой группы с помощью оператора $push.
Вот еще один способ сделать это. Комментарии находятся в стадии разработки.
db.collection.aggregate([
{ // just add index if type is array
"$match": {
"array": {"$type": "array"}
}
},
{ // map each element with incremental index
"$set": {
"array": {
"$map": {
"input": {
// produce index values
"$range": [0, {"$size": "$array"}]
},
"as": "idx",
"in": {
// merge index into each object
"$mergeObjects": [
{"index": "$$idx"},
{"$arrayElemAt": ["$array", "$$idx"]}
]
}
}
}
}
}
])
Попробуйте на mongoplayground.net.
Вам не нужен $unwind массив. $unwind может снизить производительность, если в массиве большое количество элементов. Точно так же $group также может снизить производительность из-за необходимости снова сматывать размотанные документы.
Для повышения производительности вы можете просто $map перебрать массив и использовать $indexOfArray, чтобы получить текущий индекс из родительского массива. Добавив объект с полем index, вы можете объединить его с исходным объектом на каждой итерации $map следующим образом:
db.collection.aggregate([
{
$addFields: {
"abc.array": {
$map: {
input: "$abc.array",
as: "element",
in: {
$mergeObjects: [
"$$element",
{
index: {
$indexOfArray: [
"$abc.array",
"$$element"
]
}
}
]
}
}
}
}
}
])
См. ЗДЕСЬ рабочий пример с использованием экстраполированного набора документов из вашего образца документа.