Does anyone know how to add an array element to a mongodb array and set a "virtual" order to the size of the array, all in an atomic operation?
So, something like:
db.users.updateOne(
{ _id: 1},
{ $addToSet: { images: {name: 'new image', order: "size of the array"} } }
)
The idea is to always have the last array element added have an order that is last.
Update:
Data before op:
{
_id: 1,
images: [
{ name: 'some name', order: 0 }
]
}
Data after op:
{
_id: 1,
images: [
{ name: 'some name', order: 0 },
{ name: 'new image', order: 1 }
]
}
Thank you!
2
Answers
Assuming your
order
field would be an integer field, you can use$let
to compute the next order number and use$concatArrays
to append it to the end of the array.Some scenarios:
images
already has data in it:$max
will get the largestorder
number,$add
1 to it.images
is an empty array: the$max
result will fallback to 0 due to$ifNull
images.order
is not perfectly 0-th ordered: it may have some gaps in between, or not starting from 0. It will be handled by$max
and$add
1 logic.images
is a null field or does not exists: it will be safeguarded by$ifNull
and fall back to an empty array.Mongo Playground
Note that you already keep your image details in an array, so they already have an order defined by the position in the array. So if the motivation for the
order
attribute is to query the array index later, there are other ways to do that, and it may be redundant.For example, the
$unwind
operator optionally returns an array index. You could query this instead of a custom field which needs to be separately maintained every time theimages
field is updated.