GnxR
GnxR

Reputation: 839

Update fields in an array of objects

I have a collection storing documents in the form of:

{
  "_id": ObjectId("..."),
  "begin": 2020-10-01,
  "dates": [
    { "name": "one", "created": 2020-10-10, "updated": 2020-10-11 },
    { "name": "two", "created": 2020-10-12, "updated": 2020-10-13 },
    ...
  ]
}

I want to update this collection to add 3 days to every date contained in every document of the collection. My example document would become:

{
  "_id": ObjectId("..."),
  "begin": 2020-10-04,
  "dates": [
    { "name": "one", "created": 2020-10-13, "updated": 2020-10-14 },
    { "name": "two", "created": 2020-10-15, "updated": 2020-10-16 },
    ...
  ]
}

Based on the MongoDB documentation, I wrote the following query:

db.getCollection('test').updateMany({}, [{
  $set: {
    begin: { $add: ["$begin", 3*24*60*60*1000] },
    "dates.$.created": { $add: ["$dates.$.created", 3*24*60*60*1000] },
    "dates.$.updated": { $add: ["$dates.$.updated", 3*24*60*60*1000] }
  }
}])

However, this doesn't work, because this syntax for accessing a field in an array is invalid (for instance, in the $add operation, $dates.$.created says something about $ being an illegal field name).

In the above snippet, how can I access the existing field value to update it? Is there another way?

Upvotes: 1

Views: 62

Answers (1)

turivishal
turivishal

Reputation: 36104

You are using update with aggregation pipeline and aggregation will not support $ projection update,

  • convert string type date to ISO date using $toDate, if its already date type then remove this conversation
  • $map to iterate look of dates and then add days in created and updated fields
let dayPlus = 3*24*60*60*1000;
db.getCollection('test').updateMany({},
  [{
    $set: {
      begin: {
        $add: [{ $toDate: "$begin" }, dayPlus]
      },
      dates: {
        $map: {
          input: "$dates",
          in: {
            name: "$$this.name",
            created: {
              $add: [{ $toDate: "$$this.created" }, dayPlus]
            },
            updated: {
              $add: [{ $toDate: "$$this.updated" }, dayPlus]
            }
          }
        }
      }
    }
  }]
)

Playground

Upvotes: 1

Related Questions