all() and get() load every matching document into memory at
once. That’s fine for a few hundred records, but batch jobs that enrich,
migrate, or clean up whole collections need a way to work through documents a
handful at a time. Esix provides two helpers for this: chunk and cursor.
Both fetch documents in batches using keyset pagination on the id, so memory
usage stays flat no matter how large the collection is.
chunk()
chunk(size, callback) fetches models in batches of size and hands each
batch to your callback along with a page number, starting at 1:
chunk works on any query, so you can constrain which documents are
processed:
chunk resolves to true once every batch has been processed.
Stopping Early
Returnfalse from the callback to stop processing further batches. chunk
then resolves to false:
cursor()
When you’d rather work with one model at a time,cursor() returns an async
iterator. Documents are still fetched in batches behind the scenes (1,000 per
batch by default), but your loop sees a steady stream of models:
cursor()
call entirely:
for await loop is safe and stops fetching further batches:
Iteration Order and Mutation Safety
Bothchunk and cursor iterate documents by id in ascending order. After
each batch, the next batch is fetched with an “id greater than the last one
seen” condition rather than a numeric offset. This has two important
consequences:
- Mutation safety. It is safe to update or delete the models you’ve been
handed while iterating. A hand-rolled
skip/limitloop silently skips documents when the loop body changes which documents match the query; keyset pagination does not. - Fixed ordering. Any
orderBy(),limit(), orskip()set on the query is ignored bychunkandcursor. Resumable keyset pagination requires a unique total order, so iteration is always by id ascending.
_ids must all be the same
BSON type. Documents created through Esix always use string ids, and
collections created by other tools usually use ObjectIds throughout —
both work fine. But a mixed-type collection will only iterate the first
type bracket, because MongoDB’s $gt never matches across BSON types.
If you need results in a custom order or a single bounded page, use
pagination instead.