1

I have the DB with names and dates. I need to change the old date with the date that is +3 days after that. For example oldaDate is 01.02.2015 the new one is 03.02.2015. I was trying just to put another date for all files, but that mean that all exams are going to be in one day.

$ db.getCollection('school.exam').update( {}, { $set : { "oldDay" : new ISODate("2016-01-11T03:34:54Z") } }, true, true);

The problem is just to replace old date with some random days.

Community
  • 1
  • 1
Josef
  • 87
  • 1
  • 8

1 Answers1

2

Since MongoDB doesn't yet support the $inc operator to apply on dates (view the JIRA ticket on that here), as an alternative to increment the date field, you would need to iterate the cursor returned by the find() method using the forEach() method, in the loop get convert the old date field to timestamp, add the number of days in milliseconds to the timestamp and then update the field using the $set operator.

Take advantage of using the Bulk API for bulk updates which offer better performance as you will be sending the operations to the server in batches of say 1000 which gives you a better performance as you are not sending every request to the server, just once in every 1000 requests.

The following demonstrates this approach, the first example uses the Bulk API available in MongoDB versions >= 2.6 and < 3.2. It updates all the documents in the collection by adding 3 days to the date field:

var bulk = db.getCollection("school.exam").initializeUnorderedBulkOp(),
    counter = 0,
    daysInMilliSeconds = 86400000,
    numOfDays = 3;

db.getCollection("school.exam").find({ "oldDay": { $exists : true, "$type": 2 }}).forEach(function (doc) {
    var incDate = new Date(doc.oldDay.getTime() + (numOfDays * daysInMilliSeconds ));
    bulk.find({ "_id": doc._id }).updateOne({ 
        "$set": { "oldDay": incDate }
    });

    counter++;
    if (counter % 1000 == 0) {
        bulk.execute(); // Execute per 1000 operations and re-initialize every 1000 update statements
        bulk = db.getCollection('school.exam').initializeUnorderedBulkOp();
    }
})

if (counter % 1000 != 0) { bulk.execute(); }

The next example applies to the new MongoDB version 3.2 which has since deprecated the Bulk API and provided a newer set of apis using bulkWrite():

var bulkOps = [],
    daysInMilliSeconds = 86400000,
    numOfDays = 3;

db.getCollection("school.exam").find({ "oldDay": { $exists : true, "$type": 2 }}).forEach(function (doc) { 
    var incDate = new Date(doc.oldDay.getTime() + (numOfDays * daysInMilliSeconds ));
    bulkOps.push(         
        { 
            "updateOne": { 
                "filter": { "_id": doc._id } ,              
                "update": { "$set": { "oldDay": incDate } } 
            }         
        }           
    );     
})

db.getCollection("school.exam").bulkWrite(bulkOps, { 'ordered': true });
chridam
  • 100,957
  • 23
  • 236
  • 235