Home > Software engineering >  MongoDB: Update element in an array where the index of the element is saved in the document
MongoDB: Update element in an array where the index of the element is saved in the document

Time:12-09

I have the following document structure.

{
    _id: ...,
    unique_id: 1234,
    config_no: 1,
    configs: [
        {
            data: "qwertyuiop" // random string
        },
        {
            data: "asdfghjkl" // random string
        }
    ]
}

I want to update value of data from one of the configs. The index of the config that needs to be updated is available in the config_no key.

Is there any way to update the value without querying the document.

This is what I am currently doing

doc = db.collection.findOne({"unique_id": 1234})
config_no = doc.config_no
db.collection.updateOne(
    {"unique_id": 1234},
    {"$set": {"configs." config_no ".data": "zxcvbnm"}} //"configs.1.data"
)

Following is something what i would like to achive.

db.collection.updateOne(
    {"unique_id": 1234},
    {"$set": {"configs.${config_no}.data": "zxcvbnm"}}
)

CodePudding user response:

You can $unwind with includeArrayIndex option. Use the index to perform conditional update and $merge back into the collection.

db.collection.aggregate([
  {
    $match: {
      unique_id: 1234
    }
  },
  {
    "$unwind": {
      path: "$configs",
      includeArrayIndex: "idx"
    }
  },
  {
    $set: {
      "configs.data": {
        "$cond": {
          "if": {
            $eq: [
              "$config_no",
              "$idx"
            ]
          },
          "then": "zxcvbnm",
          "else": "$configs.data"
        }
      }
    }
  },
  {
    $group: {
      _id: "$_id",
      config_no: {
        $first: "$config_no"
      },
      configs: {
        $push: "$configs"
      },
      unique_id: {
        $first: "$unique_id"
      }
    }
  },
  {
    "$merge": {
      "into": "collection",
      "on": "_id",
      "whenMatched": "merge"
    }
  }
])

Mongo Playground

  • Related