Create a bulk object and add updates to it, when it gets to a certain size call execute and then reset the bulk object and repeat.
Rough pseudocode:
var batchSize = 1000;
var progressCounter = 0;
var bulkObject = db.getCollection('XXX').initializeUnorderedBulkOp();
var sourceData = db.getCollection('SourceColl').distinct('theField');
var loopCounter = 10001;
sourceData.forEach(theItem =>{
print(`Processing: ${theItem}`)
db.getCollection.find({'theField':theItem}, {_id:1}).sort({sortField:1}).forEach(theDoc =>{
progressCounter++;
bulk.find( { _id: theDoc._id } ).update( { $set: { counter: loopCounter++ } } );
if(progressCounter % batchSize == 0){
var results = bulk.execute();
bulkObject = db.getCollection('XXX').initializeUnorderedBulkOp();
}
})
})
if(progressCounter % batchSize != 0){
var results = bulk.execute();
bulkObject = db.getCollection('XXX').initializeUnorderedBulkOp();
}
From the looks of things you want to add an incrementing fields for each group, so if you had a collection of cars, with each car document having a brand, for each brand you want to add a field to each one that increments, i.e.
{_id:0, brand:'ford'},
{_id:1, brand:'ford'},
{_id:2, brand:'ford'},
{_id:3, brand:'VW'},
{_id:4, brand:'VW'},
{_id:5, brand:'VW'},
Would get updated to:
{_id:0, brand:'ford', newField:10001},
{_id:1, brand:'ford', newField:10002},
{_id:2, brand:'ford', newField:10003},
{_id:3, brand:'VW', newField:10001},
{_id:4, brand:'VW', newField:10002},
{_id:5, brand:'VW', newField:10003},
Is this right?
To start with you could wrap the inner loop in the bulk operation block so do one (or many depending on the batch size) server call per group.
I was actually trying to add an incrementing field to a query a while back and it did not seem trivial, but you may be able to use the windowFields operator to do the grouping and adding of the new field.
How big is the collection and what’s the grouping look like in terms of number of groups and documents per group?