Reputation: 3
My question builds off this: Get only the last element of array mongoose. However, I'm using Mongoose and want to also update a field in the last element of the array, not just retrieve it.
How can I modify the last element/object in the rounds
array to change from status: started
to status: terminated
?
Document to modify
{
"_id" : "8844d3f2d25f45df8105db1ab058d7d6",
"rounds" : [
{ "status" : "offline" },
{ "status" : "paused" },
{ "status" : "started" }
],
"updatedAt" : ISODate("2020-07-05T21:21:58.823Z")
}
Seems like using negative indices would make this easy, allowing the n-1 element to be modified. I've seen many questions mention aggregation, but none modify the underlying data. I want to combine aggregation with updating a documenting.
Is it possible to use $set
with a negative index?
Upvotes: 0
Views: 1162
Reputation: 5245
As of v4.2 MongoDB does not have a straightforward way to update an array element by index.
However starting from v4.2 you can use updates with aggregation pipeline, which allow you to construct a new array based on the current array and replace the current array.
Instead of modifying the last element, you can construct a new array consisting of the first top n - 1
elements combining with a new element { status: "terminated" }
.
You can achieve this by using $slice
to get the top n - 1
elements and combine with the new element using $concatArrays
This assumes the elements only contains the field status
you you want to update a field of an array elements that contains multiple fields, you'll need to merge the updated field with the current element using $mergeObjects
Model.updateOne({ // or updateMany with your condition
_id: "8844d3f2d25f45df8105db1ab058d7d6"
}, [{
$set: {
rounds: {
$concatArrays: [ // combine arrays
{
$slice: [ // get the top n - 1 elements
"$rounds",
{ $subtract: [{ $size: "$rounds" }, 1] }
]
},,
[{ status: "terminated" }] // a new element to replace the last element
]
}
}
}])
Upvotes: 1