arraysmongodbmongoosemongodb-update

Mongoose - How to update certain subdocument value in array of objects


My collection sample data is as follows:

{
    "_id" : ObjectId("649d1b0b5e40905678a30829"),
    "slug" : "samsung-s22",
    "name" : "Samsung S22",
    "params" : [
        {
            "modelno" : "SM-S901B",
            "color"   : "White",
            "price"   : "64000",
            "_id"     : ObjectId("649e70bdd20e94bef90f2e7f")
        },
        {
            "modelno" : "SM-S901B",
            "color"   : "Black",
            "price"   : "64000",
            "_id"     : ObjectId("649e70bdd20e94bef90f2e7d")
        },
        {
            "modelno" : "SM-S901U",
            "color"   : "Black",
            "price"   : "74000",
            "_id"     : ObjectId("649e70bdd20e94bef90f2a7f")
        },
        {
            "modelno" : "SM-S901U",
            "color"   : "Black",
            "price"   : "74000",
            "_id"     : ObjectId("649e70bdd20e94bef90f2b7f")
        },
    ]
},
{
    "_id" : ObjectId("649d1b0b5e40905678a30819"),
    "slug" : "vivo-v19",
    "name" : "Vivo V19",
    "params" : [
        {
            "modelno" : "Vivo 1933",
            "color"   : "Grey",
            "price"   : "34000",
            "_id"     : ObjectId("659e70bdd20e94bef90f2e7f")
        },
        {
            "modelno" : "Vivo 1933",
            "color"   : "Black",
            "price"   : "34000",
            "_id"     : ObjectId("659e70bdd20e94bef90f2e7d")
        },
        {
            "modelno" : "Vivo 2933",
            "color"   : "Black",
            "price"   : "44000",
            "_id"     : ObjectId("659e70bdd20e94bef90f2a7f")
        },
    ]
}

What I need is to update specific model number's price value. For example in the above document, if I give condition as name = "Samsung S22" && "modelno" = "SM-S901B" and new price value as 69999, then I need to update the price value of the following params only:

{
    "modelno" : "SM-S901B",
    "color"   : "White",
    "price"   : "69999",
    "_id"     : ObjectId("649e70bdd20e94bef90f2e7f")
},
{
    "modelno" : "SM-S901B",
    "color"   : "Black",
    "price"   : "69999",
    "_id"     : ObjectId("649e70bdd20e94bef90f2e7d")
},

Solution

  • You should update the element in the params array via filtered positional operator $[<identifier>].

    db.collection.update({
      "name": "Samsung S22",
      "params.modelno": "SM-S901B"
    },
    {
      $set: {
        "params.$[param].price": "69999"
      }
    },
    {
      arrayFilters: [
        {
          "param.modelno": "SM-S901B"
        }
      ]
    })
    

    Demo @ Mongo Playground

    For Mongoose:

    You may use either of these update() methods depend on your use case:

    await collection.findOneAndUpdate({
      "name": "Samsung S22",
      "params.modelno": "SM-S901B"
    },
    {
      $set: {
        "params.$[param].price": "69999"
      }
    },
    {
      arrayFilters: [
        {
          "param.modelno": "SM-S901B"
        }
      ]
    })