Home > Mobile >  Mongoose - Update a nested object in array in MongoDB
Mongoose - Update a nested object in array in MongoDB

Time:01-18

Alright, this might have been asked quite a lot of times but none of them gives me a solution.

Here's my schema.

{ 
    "_id" : ObjectId("23453453453453"), 
    "title": "Item 01"
    "checkList" : [ 
            { 
                "ch_id" : "621eff4e0ed5c751adaa42fb", 
                "status" : "statu", 
                "dateMonthYear" : 1646286480139.0, 
                "val" : "Gopi", 
                "remarks" : "Good", 
                "_id" : ObjectId("7555777575") 
            }, 
            { 
                "ch_id" : "621eff4e0ed5c751adaa42fb", 
                "status" : "status", 
                "dateMonthYear" : 1646286480139.0, 
                "val" : "Gopi", 
                "remarks" : "Good", 
                "_id" : ObjectId("7555777575") 
            } 
    ]
}

What I want to do is update the status in the 2nd object in the checklist array. I can use the following query to update this just fine.

const itemUpdated =  await Item.updateOne(
    {_id: id, 'checklist._id': req.params.id},
    {$set: { "checklist.$.status": req.body.status }},
);

But, I want to use Mongoose method like save() to update this. Not RAW query. Because with Mongoose methods, I get extra layer of validation and middleware. I checked all over internet but only found ones with raw queries.

How to update a nested object in array with Mongoose ORM ?

CodePudding user response:

Retrieve the Item and loop to its checkList updating the status:

const item = await Item.findOne({ _id: id, 'checklist._id': req.params.id });
if (!item || item.checkList.length === 0) return;
for (let i = 0; i < item.checkList.length; i  ) {
    item.checkList[i].status = req.body.status;
}
await item.save();

CodePudding user response:

I finally found this solution that works best for this situation. I don't know why Mongoose docs are so poorly written.

If we have an array of subdocuments, we can fetch the one we need with id() method provided by Mongoose.

const item = await Item.findById(id);
checkListItem = item?.checklist.id(req.params.id);

if(checkListItem){
  checkListItem.status = req.body.status;
  item?.save();
}

This worked for me. Hope someone might find this useful!

  • Related