I have this one schema
{
_id: "123456",
id: "123",
inventory: [
{
id: "foo",
count: 0
},
{
id: "bar",
count: 3
}
]
}
I wanted every "count" keys in the inventory array to be "price" which will look like this at the end:
{
_id: "123456",
id: "123",
inventory: [
{
id: "foo",
price: 0
},
{
id: "bar",
price: 3
}
]
}
And I've tried this
Model.updateOne({ id: "123" }, { $unset: { inventory: [{ count: 1 }] } } )
But it seems to be deleting the "inventory" field itself
CodePudding user response:
The first thing here is to try to use $rename but how the docs explain:
$rename
does not work if these fields are in array elements.
So is necessary to look for another method. So you can use this update with aggregation query:
This query uses mainly $map
, $arrayToObject
and $objectToArray
. The trick here is:
- Create a new field called
inventory
(overwrite existing one) - Iterate over every value of the array with
$map
, and then for each object in the array use$objectToArray
to create an array and also iterate over that second array using again$map
. - Into this second iteration create fields
k
andv
. Fieldv
will be the same (you don't want to change the value, only the key). And for fieldk
you have to change only the one whose match with your condition, i.e. only change fromcount
toprice
. If this condition is not matched then the key remain.
db.collection.update({},
[
{
$set: {
inventory: {
$map: {
input: "$inventory",
in: {
$arrayToObject: {
$map: {
input: {$objectToArray: "$$this"},
in: {
k: {
$cond: [
{
$eq: ["$$this.k","count"]
},
"price",
"$$this.k"
]
},
v: "$$this.v"
}
}
}
}
}
}
}
}
])
Example here