Search code examples
mongodbobjectmongoosemongodb-querymongodb-update

Mongoose - Update multi objects inside an array by ID


Firstly, sorry for my bad English. Secondly, I want to ask, how to multi-update my document.

I have a row structure like this:

Data Model

[
    {
        "id": '00001',
        "exp": '192',
        "items": [
            { "qty": 23, "ID": ObjectId("kieryu35261twerts73940djr") },
            { "qty": 77, "ID": ObjectId("1240a1ffuw33dbcv6ut8888zz") },
            { "qty": 1, "ID": ObjectId("5600r0e0rr67cbd60a1234y5") },
            { "qty": 5, "ID": ObjectId("32bbd0e0rr92cdb60a4386c7") }
        ],
        "stats": [
            { "strenght": 1, "ID": ObjectId("3eruskdjfhrutiwo4059yuol3") },
            { "strenght": 2, "ID": ObjectId("3jdks0d9r2seifldvjmw0km2e") },
            { "strenght": 1, "ID": ObjectId("aslkdnasklnc2112uhnsjssad") },
            { "strenght": 5, "ID": ObjectId("1230msafmlklkmasfmcio3kms") }
        ]
    },
    {
        "id": '00002',
        "exp": '100',
        "items": [
            { "strenght": 10, "ID": ObjectId("21312kn3kaklmasklcklasmck") },
            { "strenght": 10, "ID": ObjectId("kldsafklsajdfklmsadlkaskl") }
        ],
        "stats": [
            { "strenght": 9, "ID": ObjectId("aslkclkamiior2oinrkl2adsa") },
            { "strenght": 0, "ID": ObjectId("asdoasjdosmdkl123123kmnsd") }
        ]
    }
]

I want to update one document row by finding the id of the document, and multi-deep elements by ID too. Like this:

{
    "id": '00001',
    "exp": '555',
    "items": [
        { "qty": 44, "ID": ObjectId("kieryu35261twerts73940djr") },
        { "qty": 55, "ID": ObjectId("1240a1ffuw33dbcv6ut8888zz") },
        { "qty": 66, "ID": ObjectId("5600r0e0rr67cbd60a1234y5") },
        { "qty": 77, "ID": ObjectId("32bbd0e0rr92cdb60a4386c7") }
    ],
    "stats": [
        { "strenght": 10, "ID": ObjectId("3eruskdjfhrutiwo4059yuol3") },
        { "strenght": 20, "ID": ObjectId("3jdks0d9r2seifldvjmw0km2e") },
        { "strenght": 12, "ID": ObjectId("aslkdnasklnc2112uhnsjssad") },
        { "strenght": 54, "ID": ObjectId("1230msafmlklkmasfmcio3kms") }
    ]
}

And last, just for information, I do before this:

await DataModel.findOneAndUpdate(
    { 
        "id" : idvariable // == 00001
    },
    {
        "$set" : {
            "exp" : 555,
            "items": {
                //update qty == 44 where ID == kieryu35261twerts73940djr
                //update qty == 55 where ID == 1240a1ffuw33dbcv6ut8888zz
                //update qty == 66 where ID == 5600r0e0rr67cbd60a1234y5
                //update qty == 77 where ID == 32bbd0e0rr92cdb60a4386c7
            },
            "stats": {
                //update strenght == 10 where ID == 3eruskdjfhrutiwo4059yuol3
                //update strenght == 20 where ID == 3jdks0d9r2seifldvjmw0km2e
                //update strenght == 12 where ID == aslkdnasklnc2112uhnsjssad
                //update strenght == 54 where ID == 1230msafmlklkmasfmcio3kms
            }
        }
    }
)

Please, I don't know how to update it with a single query update, or other technique. Thank you.


Solution

  • Possible, but a bit long query.

    Working on the Update with Aggregation Pipeline,

    $map - Iterate the items in the array and return a new array.

    $switch - Switch-case (statement) to match the ID of the current iterated document and update the document if matched. If all the case conditions are failed to match, remain the existing document.

    db.collection.update({
      "id": idvariable// == 00001
      
    },
    [
      {
        "$set": {
          "exp": 555,
          "items": {
            $map: {
              input: "$items",
              in: {
                $switch: {
                  branches: [
                    {
                      case: {
                        $eq: [
                          "$$this.ID",
                          "kieryu35261twerts73940djr"
                        ]
                      },
                      then: {
                        $mergeObjects: [
                          "$$this",
                          {
                            qty: 44
                          }
                        ]
                      }
                    },
                    {
                      case: {
                        $eq: [
                          "$$this.ID",
                          "1240a1ffuw33dbcv6ut8888zz"
                        ]
                      },
                      then: {
                        $mergeObjects: [
                          "$$this",
                          {
                            qty: 55
                          }
                        ]
                      }
                    },
                    {
                      case: {
                        $eq: [
                          "$$this.ID",
                          "5600r0e0rr67cbd60a1234y5"
                        ]
                      },
                      then: {
                        $mergeObjects: [
                          "$$this",
                          {
                            qty: 66
                          }
                        ]
                      }
                    },
                    {
                      case: {
                        $eq: [
                          "$$this.ID",
                          "32bbd0e0rr92cdb60a4386c7"
                        ]
                      },
                      then: {
                        $mergeObjects: [
                          "$$this",
                          {
                            qty: 77
                          }
                        ]
                      }
                    }
                  ],
                  default: "$$this"
                }
              }
            }
          },
          "stats": {
            $map: {
              input: "$stats",
              in: {
                $switch: {
                  branches: [
                    {
                      case: {
                        $eq: [
                          "$$this.ID",
                          "3eruskdjfhrutiwo4059yuol3"
                        ]
                      },
                      then: {
                        $mergeObjects: [
                          "$$this",
                          {
                            strenght: 10
                          }
                        ]
                      }
                    },
                    {
                      case: {
                        $eq: [
                          "$$this.ID",
                          "3jdks0d9r2seifldvjmw0km2e"
                        ]
                      },
                      then: {
                        $mergeObjects: [
                          "$$this",
                          {
                            strenght: 20
                          }
                        ]
                      }
                    },
                    {
                      case: {
                        $eq: [
                          "$$this.ID",
                          "aslkdnasklnc2112uhnsjssad"
                        ]
                      },
                      then: {
                        $mergeObjects: [
                          "$$this",
                          {
                            strenght: 12
                          }
                        ]
                      }
                    },
                    {
                      case: {
                        $eq: [
                          "$$this.ID",
                          "1230msafmlklkmasfmcio3kms"
                        ]
                      },
                      then: {
                        $mergeObjects: [
                          "$$this",
                          {
                            strenght: 54
                          }
                        ]
                      }
                    }
                  ],
                  default: "$$this"
                }
              }
            }
          }
        }
      }
    ])
    

    For the items and stats with ID to be updated, make sure that you need to parse as ObjectId [Note that Mongo Playground doesn't recognize your provided IDs, I manually change the dataset for those IDs as string but the concept for the update is the same].

    Sample Mongo Playground