As of 5.0 and arrival of [$setWindowFields](https://www.mongodb.com/docs/manual/reference/operator/aggregation/setWindowFields/) there is a super simple way to do this:

> db.places.aggregate([
        {$setWindowFields:{output:{batch:{$documentNumber:{}}},sortBy:{_id:1}}},
        {$set:{batch:{$ceil:{$divide:["$batch",5]}}}}
])
{ "_id" : ObjectId("680282faf8bf7676cfea7732"), "userid" : "a", "location" : "Bishan", "batch" : 1 }
{ "_id" : ObjectId("680282faf8bf7676cfea7733"), "userid" : "b", "location" : "Bukit Timah", "batch" : 1 }
{ "_id" : ObjectId("680282faf8bf7676cfea7734"), "userid" : "c", "location" : "Ang Mo Kio", "batch" : 1 }
{ "_id" : ObjectId("680282faf8bf7676cfea7735"), "userid" : "d", "location" : "Segar", "batch" : 1 }
{ "_id" : ObjectId("680282faf8bf7676cfea7736"), "userid" : "e", "location" : "Fajar", "batch" : 1 }
{ "_id" : ObjectId("680282faf8bf7676cfea7737"), "userid" : "f", "location" : "dover", "batch" : 2 }
{ "_id" : ObjectId("680282faf8bf7676cfea7738"), "userid" : "g", "location" : "Buona Vista", "batch" : 2 }
{ "_id" : ObjectId("680282faf8bf7676cfea7739"), "userid" : "h", "location" : "Marina Bay", "batch" : 2 }
{ "_id" : ObjectId("680282faf8bf7676cfea773a"), "userid" : "i", "location" : "Rocher", "batch" : 2 }
{ "_id" : ObjectId("680282faf8bf7676cfea773b"), "userid" : "j", "location" : "down town", "batch" : 2 }
{ "_id" : ObjectId("680282faf8bf7676cfea773c"), "userid" : "k", "location" : "Jurong", "batch" : 3 }
{ "_id" : ObjectId("680282faf8bf7676cfea773d"), "userid" : "l", "location" : "Pungol", "batch" : 3 }
{ "_id" : ObjectId("680282faf8bf7676cfea773e"), "userid" : "m", "location" : "One North", "batch" : 3 }
{ "_id" : ObjectId("680282faf8bf7676cfea773f"), "userid" : "n", "location" : "Cho Chu Kang", "batch" : 3 }
{ "_id" : ObjectId("680282faf8bf7676cfea7740"), "userid" : "o", "location" : "Yishun", "batch" : 3 }

The first stage, $setWindowFields adds $documentNumber to each document which is just a sequence number (1,2,3,4 etc) and the second stage converts that number to next multiple of 5 by dividing it by 5 and taking $ceil aka ceiling - next highest integer.

Note that setting a sequence number with $documentNumber requires sortBy in the $setWindowFields stage so that the order is not arbitrary like it is in your original example without any sort. You can specify any indexed field if you don’t actually care about which document goes into which batch.

Hope that helps someone
Asya

1 Like