2

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 Answer 1

1

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

Sign up to request clarification or add additional context in comments.

3 Comments

Doesn't seems to be working in my actual dataset, but thanks anyway. It gave me some idea. ibb.co/S03yRmB
You need to pass ObjectId, currently its string just wrap it ObjectId("5f86cacbe4d7c423f21faf50") and then try.
btw, you are missing an array wrapper [] around your $set without it it won't update the database.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.