// Signature
db.collection.find(query, projection, options)
// All documents in collection
db.users.find({})
// Filter: exact match
db.users.find({ city: "Mumbai" })
// Filter: range with comparison operators
db.products.find({ price: { $gt: 100, $lte: 500 } })
// Filter: logical OR
db.users.find({ $or: [{ city: "Mumbai" }, { city: "Delhi" }] })
find() Returns a Cursor — Not Data
// Cursor is ALWAYS truthy — even with 0 results
const cur = db.users.find({ name: "Ghost" })
if (cur) { ... } // always enters — cursor object is truthy regardless
// CORRECT ways to check if results exist:
cur.hasNext() // true if at least one document remains
cur.toArray().length // convert first, then check length
db.users.countDocuments({ name: "Ghost" }) // modern way to count
// Convert to array (loads all into memory — avoid on large sets)
const docs = db.users.find({}).toArray()
// Iterate with forEach (memory-efficient — processes one at a time)
db.users.find({}).forEach(doc => {
print(doc.name)
})
Cursor Batch Size
MongoDB fetches results in batches — first batch is 101 documents (or 16 MiB, whichever is smaller). Subsequent getMore ops also fetch up to 16 MiB (the 101-document cap is lifted after the first batch). This keeps memory usage low on large collections.
The "1 MB first batch" limit is outdated — it applied to MongoDB v3.3 and earlier. Modern MongoDB (v3.4+) uses 16 MiB for both the first and subsequent batches. If documents are large (e.g. 1 MB each), only ~16 documents fit in the first batch, not 101.
find({}) on an empty collection returns an empty cursor — it does not throw an error or return null.