I have a database with data like this:
[{
"_id": {
"$oid": "664baf560b9539e48fbc6ed1"
},
"name": "first assignment",
"next": {
"$oid": "664baf620b9539e48fbc6ed2"
},
"preview": null,
"date": {
"$date": "2024-04-20T10:00:00.000Z"
}
},
{
"_id": {
"$oid": "664baf620b9539e48fbc6ed2"
},
"name": "second assignment",
"next": {
"$oid": "664baf6d0b9539e48fbc6ed3"
},
"preview": {
"$oid": "664baf560b9539e48fbc6ed1"
},
"date": {
"$date": "2024-04-21T10:00:00.000Z"
}
},
{
"_id": {
"$oid": "664baf6d0b9539e48fbc6ed3"
},
"name": "third assignment",
"next": {
"$oid": "664baf8d0b9539e48fbc6ed4"
},
"preview": {
"$oid": "664baf620b9539e48fbc6ed2"
},
"date": {
"$date": "2024-04-22T10:00:00.000Z"
}
},
{
"_id": {
"$oid": "664baf8d0b9539e48fbc6ed4"
},
"name": "fourth assignment",
"next": null,
"preview": {
"$oid": "664baf6d0b9539e48fbc6ed3"
},
"date": {
"$date": "2024-04-23T10:00:00.000Z"
}
}
]
The next and preview fields refer to other documents in the same collection.
So, suppose I receive the ID of fourth assignment (664baf8d0b9539e48fbc6ed4). I need to create a new document with the same structure in which preview is the ID of the fourth assignment but also update the fourth assignment document to assign the ID of the new created document to next.
Is this flow possible in an aggregation or should I use traditional operations separately?
2
Answers
If you can deduce the content of 5th assignment when you have received the id of 4th assignment, you can
$set
thenext
field of 4th assignment and$unionWith
the 5th assignment you have in a$documents
stage. Finally do a$merge
to update the 2 documents into the collection.Mongo Playground
If you’re okay to create the ObjectId of the new "fifth" document in your application code in PyMongo, Mongoose, etc. (instead of letting it be set by MongoDB upon insert) then this can be done in a single aggregation pipeline.
$merge
will update fields of existing docs and create new docs for those which don’t exist._id
to identify the existing doc and only thenext
field with the updated value._id
; and this will get inserted into the collection.What I’ve done below is:
Create an Array of two docs, one for the existing "fourth" with updated values and one for the new "fifth" with all fields.
By using
$mergeObjects
, the fifth doc can inherit all the fields of the fourth and then specify only the one’s we want to override –_id
,preview
,name
,date
.next
is alreadynull
from the current value of "fourth" in this stage so remains null in the new docotherField: "other value"
is not specified for the fifth but is inherited from the fourth.Unwind the array to create two docs; replace the placeholders as the docs; merge.
Mongo Playground