I have following document on which the update needs to be done.
{
"_id": "Colorcode_1",
"Combination": [
{
"color": [
{
"mixture": [
"Red",
"Green"
]
}
],
"code": "Maroon"
},
{
"color": [
{
"mixture": [
"Yellow",
"Green"
]
}
],
"code": "Light Green"
}
]
}
Now what I need to do is to update the document by adding the value "Blue" in the "mixture" field where "code" is "Maroon". Something like this. This needs to be done using $addToSet
{
"_id": "Colorcode_1",
"Combination": [
{
"color": [
{
"mixture": [
"Red",
"Green",
"Blue"
]
}
],
"code": "Maroon"
},
{
"color": [
{
"mixture": [
"Yellow",
"Green"
]
}
],
"code": "Light Green"
}
]
}
Any help regarding this would be highly helpful.
CodePudding user response:
I found this update difficult because of the data model, and I'm hoping you'll get a better/simpler answer.
Anyway, here's one way you could do it. I would test this on more/different data to insure it's correct.
db.collection.update({
"_id": "Colorcode_1",
"Combination.code": "Maroon"
},
[
{
"$set": {
"Combination": {
"$map": {
"input": "$Combination",
"as": "elem",
"in": {
"$cond": [
{ "$eq": [ "$$elem.code", "Maroon" ] },
{
"$mergeObjects": [
"$$elem",
{
"color": {
"$map": {
"input": "$$elem.color",
"as": "colorElem",
"in": {
"$cond": [
{
"$reduce": {
"input": { "$objectToArray": "$$colorElem" },
"initialValue": false,
"in": {
"$or": [
"$$value",
{ "$eq": [ "$$this.k", "mixture" ] }
]
}
}
},
{
"mixture": {
"$setUnion": [ "$$colorElem.mixture", [ "Blue" ] ]
}
},
"$$colorElem"
]
}
}
}
}
]
},
"$$elem"
]
}
}
}
}
}
])
Try it on mongoplayground.net.
CodePudding user response:
Here is option with arrayFilters:
db.collection.update({
"Combination.code": "Maroon"
},
{
"$addToSet": {
"Combination.$[x].color.$[y].mixture": "Blue"
}
},
{
arrayFilters: [
{
"x.code": "Maroon"
},
{
"y.mixture": {
$exists: true
}
}
]
})
Explained:
- Filter all documents having code:Marron , good to have index on this field if collection is big
- Use arrayFilter x.code to add the array element to mixture if mixture exists ( identified by y arrayFilter)