Find() & FindOne() Methods
find(filter) returns a cursor — an iterable handle to matching documents. findOne(filter) returns the first match as a single document or null. Both accept an optional projection as the second argument.
find() and findOne() basics
find(filter) returns a cursor — an iterable handle to matching documents. findOne(filter) returns the first match as a single document or null. Both accept an optional projection as the second argument.
Real-life example: find() is like searching a library catalog for all books by an author. findOne() stops at the first match — like looking up one student by roll number.
use rishtaara
// All products
db.products.find()
// Filter — implicit AND between fields
db.products.find({ category: "electronics", price: { $lt: 1000 } })
// findOne — single document or null
db.students.findOne({ name: "Asha Khan" })
// { _id: ObjectId("..."), name: "Asha Khan", grade: 10, ... }
db.students.findOne({ name: "Nobody" })
// null
// Equality shorthand — these are equivalent
db.products.find({ category: "electronics" })
db.products.find({ category: { $eq: "electronics" } })Projection — return only what you need
Projection controls which fields appear in results. Use 1 to include and 0 to exclude. You cannot mix inclusion and exclusion except for _id.
Real-life example: Projection is like photocopying only the name and grade columns from a report — not the entire page.
// Include name and price only; hide _id
db.products.find(
{ category: "electronics" },
{ name: 1, price: 1, _id: 0 }
)
// Exclude heavy fields from all products
db.products.find(
{},
{ description: 0, images: 0, reviews: 0 }
)
// findOne with projection
db.students.findOne(
{ grade: 12 },
{ name: 1, "address.city": 1, _id: 0 }
)sort(), skip(), and limit()
Chain sort(), skip(), and limit() on a find cursor for ordered and paginated results. Sort values: 1 ascending, -1 descending.
Real-life example: sort + skip + limit is like flipping to page 3 of a sorted phone book — skip the first 20 names, show the next 10.
- Always sort before skip/limit for consistent pagination.
- Large skip values are slow — use range queries on _id or createdAt for deep pagination.
- Compound indexes should match your sort fields for performance.
// Cheapest electronics first, top 5
db.products
.find({ category: "electronics" })
.sort({ price: 1 })
.limit(5)
// Most expensive products
db.products.find().sort({ price: -1 }).limit(10)
// Pagination: page 3, 10 per page (skip first 20)
const page = 3
const pageSize = 10
db.products
.find({ category: "stationery" })
.sort({ name: 1 })
.skip((page - 1) * pageSize)
.limit(pageSize)
// Sort by multiple fields: grade ascending, then name ascending
db.students.find().sort({ grade: 1, name: 1 })countDocuments()
countDocuments(filter) counts documents matching a filter — accurate but scans matching docs. estimatedDocumentCount() is fast but approximate and ignores filters.
Real-life example: countDocuments is like asking 'How many grade-10 students?' — exact count. estimatedDocumentCount is like glancing at a 'approximately 500 students' sign.
// Exact count with filter
db.products.countDocuments({ category: "electronics" })
// 47
db.students.countDocuments({ grade: { $gte: 10 }, active: true })
// 156
// Count documents with a specific field present
db.students.countDocuments({ email: { $exists: true } })
// Fast approximate total (no filter allowed)
db.products.estimatedDocumentCount()
// ~500 (may differ slightly from true count)
// Pagination helper
const total = db.products.countDocuments({ category: "electronics" })
const totalPages = Math.ceil(total / 10)
print("Total pages:", totalPages)