How does one properly increment many dates in mongoDB?
The problem is that my $exists
query is (obviously, on second look) in the wrong place. Documents were being returned that, surely enough, didn't include my_date
.
Here's the patched up function, which works as expected.
var incrementDates = function() {
db.blah.find({ ... , my_date : { $exists : true } ).forEach(function(doc) {
db.blah.update(
{ _id : doc._id }
, { $set : { my_date : new Date(doc.my_date.getTime() + 86400000) }}
);
});
}
Starting in Mongo 5.0
, it's a nice use case for the new $dateAdd
aggregation operator:
// { "date" : ISODate("2020-04-05T07:14:17.802Z"), "x" : "y" }
db.collection.updateMany(
{ date : { $exists : true } },
[{ $set: { date: { $dateAdd: { startDate: "$date", unit: "day", amount: 1 } } } }]
)
// { "date" : ISODate("2020-04-06T07:14:17.802Z"), "x" : "y" }
The first part
{ date : { $exists : true } }
is the match query, filtering which documents to update (in our case all documents having thedate
field).The second part
[{ $set: { date: { $dateAdd: { startDate: "$date", unit: "day", amount: 1 } } } }]
, updates the value of thedate
field by adding ($dateAdd
)1
(amount
)day
(unit
) to$date
(startDate
).
Starting in Mongo 4.2
, db.collection.update()
can accept an aggregation pipeline, finally allowing the update of a field based on its own value; thus avoiding inefficient find/foreach patterns.
Also, you were looking at the $inc
operator to add a day, but now that we can use an aggregation pipeline as an update, the $add
operator can be used:
// { "date" : ISODate("2020-04-05T07:14:17.802Z"), "x" : "y" }
db.collection.updateMany(
{ date : { $exists : true } },
[{ $set: { date: { $add: ["$date", 24*60*60000] } } }]
)
// { "date" : ISODate("2020-04-06T07:14:17.802Z"), "x" : "y" }
The first part
{ date : { $exists : true } }
is the match query, filtering which documents to update (in our case all documents having thedate
field).The second part
[{ $set: { date: { $add: ["$date", 24*60*60000] } } }]
is the update aggregation pipeline (note the squared brackets signifying the use of an aggregation pipeline).$set
is a new aggregation operator and an alias of$addFields
. Then any aggregation operator can be used within the$set
stage; in our case a simple$add
ition between the existing date and the representation of a day in milliseconds.