Reputation: 149
Model structure:
{ _id: String, calc: [ { preset: String, datasets: [ { _id: String } ] } ] }
API route:
router.put('/:gameId/:preset/:datasetId', (req, res) => {
Game.findOneAndUpdate({ _id: req.params.gameId, 'calc.preset': req.params.preset, 'calc.datasets._id': req.params.datasetId },
{ $set: { 'calc.$.datasets.$': req.body } })
.then(() => res.status(200).json({ ...req.body, _id: req.params.datasetId }))
.catch(err => res.status(500).json({ error: err }));
});
If I was to update an object inside calc array then I would: $set: { 'calc.$': newCalc }
, so I followed the same approach in order to update an object that is inside datasets array, that is inside an object, that is inside calc array, however, $set: { 'calc.$.datasets.$': newDataset }
doesn't work.
How to update an object with _id: req.params.datasetId, inside datasets array, that is inside calc array's object where the preset: req.params.preset?
In short: { calc: [ { datasets: [ { set this object to a new dataset } ] } }
Upvotes: 3
Views: 99
Reputation: 12817
you can use $[]
positional-all to updated nested array elements, mongo doc for $[]
query
db.t14.update(
{},
{ $set: { "calc.$[].datasets.$[elem].name": "updated" } },
{ arrayFilters: [ { "elem": "x1" } ], multi: true}
)
sample collection with a document
> db.t14.findOne()
{
"_id" : 1,
"calc" : [
{
"preset" : "abc",
"datasets" : [
{
"_id" : "x1",
"name" : "n1"
},
{
"_id" : "x2",
"name" : "n2"
}
]
}
]
}
update
> db.t14.update({},{$set: { "calc.$[].datasets.$[elem].name": "newname" } },{ arrayFilters: [{ "elem.name": "n1" }], multi: true})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
post update
> db.t14.findOne()
{
"_id" : 1,
"calc" : [
{
"preset" : "abc",
"datasets" : [
{
"_id" : "x1",
"name" : "newname"
},
{
"_id" : "x2",
"name" : "n2"
}
]
}
]
}
>
Upvotes: 1