'Overwrite value and create key while update query in mongodb
I have a mongodb collection that looks like this:
{
"_id" : ObjectId("60471bd482c0da3c0e70d26f"),
"owner" : "John",
"propAvailable" : {
"val1" : true
}
},
{
"_id" : ObjectId("60471bd482c0da3c0e76523f"),
"owner" : "Matt",
"propAvailable" : {
"val1" : {
"val2" : true
}
}
I need to run an update query on this collection that will update the value of the 'propAvailable' key such that
db.collection('props').update({'owner' : 'John'} , {$set : {'propAvailable.val1.val2' : true}});
This query works if the document already looks like the second one but gives the error:
Cannot create field 'val2' in element {'val1': true} if the document format is the first one. Is there a way to write this query so that it overwrites the boolean 'true' and replaces it with the object {'val2' : true}
Solution 1:[1]
You can use:
db.collection.update({
"owner": "John"
},
{
$set: {
"propAvailable.val1": {
val2: true
}
}
})
To create val2: true inside propAvailable.val1 and replace its current content.
As you can see working on the playground
Solution 2:[2]
If you're using Mongo version 4.2+ you can use pipelined updates to achieve this, like so:
db.collection.updateMany({
owner: "John"
},
[
{
$set: {
"propAvailable.val1": {
$mergeObjects: [
{
$cond: [
{
$eq: [
"object",
{
$type: "$propAvailable.val1"
}
]
},
"$propAvailable.val1",
{}
]
},
{
val2: true
}
]
}
}
},
])
For older mongo versions this is impossible to do in 1 query if objects potentially have additional fields under val1 you want to preserve. You will have to either read and update, or execute two different updates for each case.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | |
| Solution 2 | Tom Slabbaert |
