Update Two Layer Nested Object Based On The Id
Solution 1:
You can actually sort your problem out with the update method, but you have to do it in a different way if you are using MongoDB 4.2 or later. The second parameter can be the $set
operation you want to perform or an aggregation
pipeline. Using the later you have more liberty shaping the data. This is the way you can solve your problem, I will breakdown after:
db.collection.update({
"cards.advanced.unit": 2
},
[
{
$set: {
"cards.advanced": {
$map: {
input: "$cards.advanced",
as: "adv",
in: {
cards: {
$map: {
input: "$$adv.cards",
as: "advcard",
in: {
$cond: [
{
$eq: [
"$$advcard.id",
"main-2-1"
]
},
{
title: "this is a NEW updated card",
id: "$$advcard.id"
},
"$$advcard"
]
}
}
},
unit: "$$adv.unit"
}
}
}
}
}
],
{
new: true,
});
First with use the update method passing three parameters:
- Filter query
- Aggregation pipeline
- Options. Here I just used
new: true
to return the updated document and make it easier to test.
This is the structure:
db.collection.update({
"cards.advanced.unit": 2
},
[
// Pipeline
],
{
new: true,
});
Inside the pipeline we only need one stage, the $set
to replace the property advanced
with an array we will create.
...
[
{
$set: {
"cards.advanced": {
// Our first map
}
}
}
]
...
We first map the advanced
array to be able to map the nested cards array after:
...
[
{
$set: {
"cards.advanced": {
$map: {
input: "$cards.advanced",
as: "adv",
in: {
// Here we will map the nested array
}
}
}
}
}
]
...
We use the variable we declared on the first map and which contains the advanced array current item being mapped ( adv
) to access and map the nested "cards" array ( $$adv.cards
):
...
[
{
$set: {
"cards.advanced": {
$map: {
input: "$cards.advanced",
as: "adv",
in: {
cards: {
$map: {
input: "$$adv.cards",
as: "advcard",
in: {
// We place our condition to check for the chosen card here
}
}
},
unit: "$$adv.unit",
}
}
}
}
}
]
...
Lastly we check if the current card id is equal to the id being searched $eq: [ "$$advcard.id", "main-2-1" ]
and return the new card if it matches or the current card:
...
{
$cond: [
{
$eq: [
"$$advcard.id",
"main-2-1"
]
},
{
title: "this is a NEW updated card",
id: "$$advcard"
},
"$$advcard"
]
}
...
Here is a working example of what is described: https://mongoplayground.net/p/xivZGNeD8ng
Post a Comment for "Update Two Layer Nested Object Based On The Id"