skip to Main Content
{
  _id: ObjectId("65bc98f235375d1d97621e06"),
  name: 'Aspirin',
  type: 'Pain Relief',
  forms: [
    {
      formType: 'TabletsData',
      strength: '100mg',
      dosageInstructions: [
        {
          time: 'Morning',
          instructions: [
            {
              step: 1,
              text: 'Take 1 tablet with breakfast.',
              _id: ObjectId("65bc98f235375d1d97621e09")
            },
            {
              step: 2,
              text: 'Drink a full glass of water.',
              _id: ObjectId("65bc98f235375d1d97621e0a")
            }
          ],
          _id: ObjectId("65bc98f235375d1d97621e08")
        },
        {
          time: 'Evening',
          instructions: [
            {
              step: 1,
              text: 'Take 1 tablet with dinner.',
              _id: ObjectId("65bc98f235375d1d97621e0c")
            },
            {
              step: 2,
              text: 'Avoid taking on an empty stomach.',
              _id: ObjectId("65bc98f235375d1d97621e0d")
            }
          ],
          _id: ObjectId("65bc98f235375d1d97621e0b")
        }
      ],
      _id: ObjectId("65bc98f235375d1d97621e07")
    },
    {
      formType: 'Capsule',
      strength: '200mg',
      dosageInstructions: [
        {
          time: 'Afternoon',
          instructions: [
            {
              step: 1,
              text: 'Take 1 capsule in the afternoon.',
              _id: ObjectId("65bc98f235375d1d97621e10")
            },
            {
              step: 2,
              text: 'Take with or after food.',
              _id: ObjectId("65bc98f235375d1d97621e11")
            }
          ],
          _id: ObjectId("65bc98f235375d1d97621e0f")
        },
        {
          time: 'Night',
          instructions: [
            {
              step: 1,
              text: 'Take 1 capsule before bedtime.',
              _id: ObjectId("65bc98f235375d1d97621e13")
            },
            {
              step: 2,
              text: 'Avoid taking with dairy products.',
              _id: ObjectId("65bc98f235375d1d97621e14")
            }
          ],
          _id: ObjectId("65bc98f235375d1d97621e12")
        }
      ],
      _id: ObjectId("65bc98f235375d1d97621e0e")
    }
  ],
  ingredients: [
    'Acetylsalicylic Acid',
    'Inactive Ingredient 1',
    'Inactive Ingredient 2'
  ],
  __v: 0
}

          

2

Answers


  1. You can use the updateMany method to change the text value of all matching documents.

    From your sample documents that match step : 1 you have different text for different times of the day. I presume you don’t want to update every single text to be the same value so here is an example that will set the text to "NEW VALUE" only when step : 1 and time: "Morning"

    const queryStep = 1;
    const queryTime = "Morning";
    db.collection.updateMany({
      "forms.dosageInstructions.instructions.step": queryStep
    },
    {
      $set: {
        "forms.$[].dosageInstructions.$[a].instructions.$[b].text": "NEW VALUE"
      }
    },
    {
      arrayFilters: [
        {
          "a.time": queryTime
        },
        {
          "b.step": queryStep
        }
      ]
    })
    

    See HERE for a working example of update on mongoplayground.

    You have __v property which suggests mongoose. An example using mongoose would be:

    const queryStep = 1;
    const queryTime = "Morning";
    const result = await MedicineModel.updateMany({
      "forms.dosageInstructions.instructions.step": queryStep
    },
    {
      $set: {
        "forms.$[].dosageInstructions.$[a].instructions.$[b].text": "NEW VALUE"
      }
    },
    {
      arrayFilters: [
        {
          "a.time": queryTime
        },
        {
          "b.step": queryStep
        }
      ]
    })
    
    Login or Signup to reply.
  2. You can also update multiple nested array object elements conditionally in multiple documents via the following update/aggregation query ( mongoDB v.4.2+ ):

    db.collection.update({ "forms.dosageInstructions.instructions.step": 1 },
    [
     {
    "$addFields": {
      "forms": {
        "$map": {
          "input": "$forms",
          "as": "f",
          "in": {
            $mergeObjects: [
              "$$f",
              {
                "dosageInstructions": {
                  "$map": {
                    "input": "$$f.dosageInstructions",
                    "as": "d",
                    "in": {
                      $mergeObjects: [
                        "$$d",
                        {
                          "instructions": {
                            "$map": {
                              "input": "$$d.instructions",
                              "as": "i",
                              "in": {
                                $cond: {
                                  if: {
                                    $eq: [
                                      "$$i.step",
                                      1
                                    ]
                                  },
                                  then: {
                                    $mergeObjects: [
                                      "$$i",
                                      {
                                        "text": "New Value"
                                      }
                                    ]
                                  },
                                  else: "$$i"
                                }
                              }
                            }
                          }
                        }
                      ]
                    }
                  }
                }
                }
               ]
             }
           }
         }
        }
       }
       ],
       {
        multi: true
       })
    

    Explanation:

    1. Match only documents having at least one step=1
    2. $addFileds->$map over the 3x nested arrays and use $mergeObjects[] changing via $cond only the nested element having step=1 with the text:"New Value"

    Playground

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search