iwantcoding.com
🔥 Daily 👥 Rooms 🏆 Top Log in Sign up

find / findOne

The find() method runs a query and returns a cursor. Combined with projections, sort, limit, and skip, it covers 80% of read patterns — with indexes doing the heavy lifting.

Filters, projections, cursor patterns

EXAMPLE
// 1) Filter — equality
await db.users.findOne({ email: 'ada@example.com' });
await db.users.find({ status: 'active' }).toArray();

// 2) Comparison operators
await db.orders.find({ total: { $gt: 100 } }).toArray();
await db.orders.find({ total: { $gte: 100, $lt: 500 } }).toArray();
await db.users.find({ age: { $in: [18, 21, 25] } }).toArray();
await db.users.find({ role: { $ne: 'admin' } }).toArray();

// 3) Existence / type
await db.users.find({ deletedAt: { $exists: false } }).toArray();
await db.events.find({ payload: { $type: 'object' } }).toArray();

// 4) Logical — $and (implicit), $or, $nor
await db.posts.find({
    status: 'published',
    $or: [
        { category: 'news' },
        { tags: 'featured' },
    ],
}).toArray();

// 5) Array queries
await db.users.find({ tags: 'newsletter' }).toArray();              // tags contains 'newsletter'
await db.users.find({ tags: { $all: ['vip', 'beta'] } }).toArray();  // contains BOTH
await db.orders.find({ 'items.sku': 'A-100' }).toArray();           // any item has sku
await db.orders.find({ items: { $size: 0 } }).toArray();             // empty array

// 6) Element-match — array element matching ALL conditions
await db.orders.find({
    items: { $elemMatch: { sku: 'A-100', qty: { $gte: 5 } } },
}).toArray();

// 7) Regex
await db.users.find({ email: { $regex: /@example\.com$/i } }).toArray();

// 8) Projection — return only the fields you need
await db.users.find({}, { projection: { name: 1, email: 1, _id: 0 } }).toArray();
await db.posts.find({}, { projection: { body: 0 } }).toArray();   // exclude one field

// 9) Cursor methods
await db.posts.find({ status: 'published' })
    .sort({ createdAt: -1 })
    .skip(40)
    .limit(20)
    .toArray();

// 10) Stream large results — never load to memory
const cursor = db.events.find({});
for await (const doc of cursor) {
    await process(doc);    // backpressure-aware
}

// 11) Count
await db.users.countDocuments({ status: 'active' });
// estimatedDocumentCount() is faster but only the total

// 12) Explain — what index is it using?
await db.posts.find({ status: 'published' }).sort({ createdAt: -1 }).explain('executionStats');

Why it matters

Use countDocuments for filtered counts; estimatedDocumentCount for whole-collection. The latter reads metadata in milliseconds; the former runs a real query.

Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.

Example

Example
db.customers.findOne({ name: 'Ada' });
db.customers.find({ age: { $gte: 30 } });
Try it Yourself »

Exercise

Find every active user.

db.users.find({ active: });

Discussion

Loading…