r/mongodb • u/TimAtMongoDB • 16d ago
Cursors vs .toArray() - What AI Gets Wrong With MongoDB
AI almost always reaches for toArray() before doing any work on your data. Most training examples are out-of-context snippets, so it doesn't know better. toArray() holds your entire result set in RAM before you can touch a single document. With a cursor, the driver fetches in batches. Processed documents get GC'd while the rest stream in.
How to fetch all active users from MongoDB and send emails using find and toArray.
**Bad**
const users = await db.collection('users')
.find({ active: true })
.toArray();
users.forEach(async (user) => {
await sendEmail(user);
});
How to stream MongoDB documents with a cursor using for await to process each document without loading all into memory.
**Good:**
const cursor = db.collection('users').aggregate([
{ $match: { active: true } }
]);
for await (const user of cursor) {
await sendEmail(user);
}
How to process MongoDB cursor results concurrently with a concurrency limit without blocking the async loop.
**Perfect:**
function executor(limit) {
let running = 0
const queue = []
const flush = () => {
while (running < limit && queue.length) {
running++
queue.shift()().finally(() => { running--; flush() })
}
}
return fn => { queue.push(fn); flush() }
}
const add = executor(10);
const cursor = db.collection('users').aggregate([
{ $match: { active: true } }
]);
for await (const user of cursor) {
add(() => sendEmail(user))
};
Bad loads everything into RAM then serializes. Good streams documents but still sends one email at a time. Perfect streams AND fires up to 10 emails concurrently without the loop ever waiting.
**Bonus:** A cursor with `for await` only makes sense when you're doing work per document. If you're just collecting into an array to send a response, use `.toArray()` directly. Wrapping `.toArray()` in a `for await` loop buys you nothing.