Mongodb Update subdocument values matching subdocument and without altering other fields

41 views Asked by At

I have a schema like this

{
    "_id": "5f86da4b5bb9a62742371409",
    "status" : true,
    "doc": [
      {
        "_id": "5f86cacbe4d7c423f21faf50",
        "a": 4,
        "b": null
      },
      {
        "_id": "5f86cb01a1ca5124063299c1",
        "a": 6,
        "b": null

      }
    ]
}

And I have an update in the form of


[
      {
        "_id": "5f86cacbe4d7c423f21faf50",
        "b": 90
      },
      {
        "_id": "5f86cb01a1ca5124063299c1",
        "b": 45

      }
    ]

How can I update the collection to end up like this?

{
    "_id": "5f86da4b5bb9a62742371409",
    "status" : true,
    "doc": [
      {
        "_id": "5f86cacbe4d7c423f21faf50",
        "a": 4,
        "b": 90
      },
      {
        "_id": "5f86cb01a1ca5124063299c1",
        "a": 6,
        "b": 45

      }
    ]
}

Basically I want to update the subdocument with specific keys only (leaving other keys intact)

1

There are 1 answers

3
turivishal On BEST ANSWER

You can use update with aggregation pipeline from MongoDB 4.2,

  • $map to iterate loop of array doc and inside it iterate through updateDocs array, it will return matching b, and then $mergeObjects will return updated document,
let updateDocs = [
  { "_id": mongoose.Types.ObjectId("5f86cacbe4d7c423f21faf50"), "b": 90 },
  { "_id": mongoose.Types.ObjectId("5f86cb01a1ca5124063299c1"), "b": 45 }
];

db.collection.updateMany({},
[
  {
    $set: {
      doc: {
        $map: {
          input: "$doc",
          as: "d",
          in: {
            $mergeObjects: [
              "$$d",
              {
                $reduce: {
                  input: updateDocs,
                  initialValue: {},
                  in: {
                    $cond: [
                      { $eq: ["$$this._id", "$$d._id"] },
                      { b: "$$this.b" },
                      "$$value"
                    ]
                  }
                }
              }
            ]
          }
        }
      }
    }
  }
]
)

Playground