How to limit number of updating documents in mongodb

Mongodb

Mongodb Problem Overview


How to implement somethings similar to db.collection.find().limit(10) but while updating documents?

Now I'm using something really crappy like getting documents with db.collection.find().limit() and then updating them.

In general I wanna to return given number of records and change one field in each of them.

Thanks.

Mongodb Solutions


Solution 1 - Mongodb

You can use:

db.collection.find().limit(NUMBER_OF_ITEMS_YOU_WANT_TO_UPDATE).forEach(
    function (e) {
        e.fieldToChange = "blah";
        ....
        db.collection.save(e);
    }
);

(Credits for forEach code: https://stackoverflow.com/questions/3788256/mongodb-updating-documents-using-data-from-the-same-document/3792958#3792958)

What this will do is only change the number of entries you specify. So if you want to add a field called "newField" with value 1 to only half of your entries inside "collection", for example, you can put in

db.collection.find().limit(db.collection.count() / 2).forEach(
    function (e) {
        e.newField = 1;
        db.collection.save(e);
    }
);

If you then want to make the other half also have "newField" but with value 2, you can do an update with the condition that newField doesn't exist:

db.collection.update( { newField : { $exists : false } }, { $set : { newField : 2 } }, {multi : true} );

Solution 2 - Mongodb

Using forEach to individually update each document is slow. You can update the documents in bulk using

ids = db.collection.find(<condition>).limit(<limit>).map(
    function(doc) {
        return doc._id;
    }
);
db.collection.updateMany({_id: {$in: ids}}, <update>})

Solution 3 - Mongodb

The solutions that iterate over all objects then update them individually are very slow.

Retrieving them all then updating simultaneously using $in is more efficient.

ids = People.where(firstname: 'Pablo').limit(10000).only(:_id).to_a.map(&:id)
People.in(_id: ids).update_all(lastname: 'Cantero')

The query is written using Mongoid, but can be easily rewritten in Mongo Shell as well.

Solution 4 - Mongodb

Unfortunately the workaround you have is the only way to do it AFAIK. There is a boolean flag multi which will either update all the matches (when true) or update the 1st match (when false).

Solution 5 - Mongodb

As the answer states there is still no way to limit the number of documents to update (or delete) to a value > 1. A workaround to use something like:

db.collection.find(<condition>).limit(<limit>).forEach(function(doc){db.collection.update({_id:doc._id},{<your update>})})

Solution 6 - Mongodb

If your id is a sequence number and not an ObjectId you can do this in a for loop:

let batchSize= 10;
for (let i = 0; i <= 1000000; i += batchSize) { 
  db.collection.update({$and :[{"_id": {$lte: i+batchSize}}, {"_id": {$gt: i}}]}),{<your update>})
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionawsumView Question on Stackoverflow
Solution 1 - MongodbNickView Answer on Stackoverflow
Solution 2 - MongodbbayleeView Answer on Stackoverflow
Solution 3 - MongodbPablo CanteroView Answer on Stackoverflow
Solution 4 - Mongodblobster1234View Answer on Stackoverflow
Solution 5 - MongodbNonosView Answer on Stackoverflow
Solution 6 - MongodbMartin P.View Answer on Stackoverflow