mongodbMongo DB NoSQL 

How to update nested sub-documents in Mongo DB

Updating sub-documents in NoSQL Mongo DB is bit trickey, so here we have come up with an solution how to update level 1 and level 2 nested subdocuments.

Lets Consider below document as example:

{
id: 1, 
 forecasts: [ { 
             forecast_id: 123, 
             name: "Forecast 1", 
             levels: [ 
                { 
                    levelid:1221
                    levelname: "proven", 
                    configs: [
                            { 
                              config: "Custom 1",
                              variables: [{ x: 1, y:2, z:3}]
                            }, 
                            { 
                              config: "Custom 2",
                              variables: [{ x: 10, y:20, z:30}]
                            }, 
                    ]
                }, 
                { 
                    levelid:1221
                    levelname: "likely", 
                    configs: [
                            { 
                              config: "Custom 1",
                              variables: [{ x: 1, y:2, z:3}]
                            }, 
                            { 
                              config: "Custom 2",
                              variables: [{ x: 10, y:20, z:30}]
                            }, 
                    ]
                }
            ]
        }, 
    ]
}

For the above document level, 1 update operation looks like below. Here we are updating forecast’s first id name from “Forecast 1” to “New Forecast 1”  for this one updateOne finds works fine. as written in below code

db.weather.updateOne({
                    "id": ObjectId("1"),
                    "forecasts.forecast_id": ObjectId("123")
                },
                { $set: { "forecasts.$.name": "New forecast 1" } }).then((result) => {
                    resolve(result);
                }, (err) => {
                    reject(err);
                });

For the above document level 2 update operation looks like below. Here we are updating forecasts first id levels levelid:1221 levelname from “proven” to “new proven”. Here to select and set second level subdocument we used Mongo DB  arrayFilters  and also $eleMatch

db.weather.updateOne({
                    "_id": ObjectId("1"), //this is level O select
                    "forecasts": {
                        "$elemMatch": {
                            "forecast_id": ObjectId("123"), //this is level one select
                            "levels.levelid": ObjectId("1221") // this is level to select
                        }
                    }
                },
                    {
                        "$set": {
                            "forecasts.$[outer].levels.$[inner].levelname": "New proven",
                        }
                    },
                    {
                        "arrayFilters": [
                            { "outer.forecast_id": ObjectId("123") }, 
                            { "inner.levelid": ObjectId("1221") }
                        ]
                    }).then((result) => {
                        resolve(result);
                    }, (err) => {
                        reject(err);
                    });

arrayFilter :In the update document, use the $[<identifier>] filtered positional operator to define an identifier, which you then reference in the array filter documents. You cannot have an array filter document for an identifier if the identifier is not included in the update document.

Also Read:  How to bulk import/export data in MongoDB Atlas

$eleMatch: The $elemMatch operator limits the contents of an <array> field from the query results to contain only the first element matching the $elemMatch condition.

The $ operator projects the first matching array element from each document in a collection based on some condition from the query statement.

The $elemMatch projection operator takes an explicit condition argument. This allows you to project based on a condition not in the query, or if you need to project based on multiple fields in the array’s embedded documents. See Array Field Limitations for an example.

If you have any Query about the methods used above, plesase comment down below and we will get back to you soon. 

Related posts