MongoDB Cheat Sheet
5–15 minute quick revision. Scan the reminders. Click anything rusty to jump into Learn.
MongoDB Mental Model
LearnData
- Database
- Collection
- Document
- Field
Runtime
- Application
- MongoDB Driver
- Connection Pool
- MongoDB
Documents are BSON (typed JSON). `_id` is required. One document write is atomic.
CRUD
Learndb.users.insertOne({
name: "Rahul",
age: 28,
city: "Bangalore"
})db.users.find({ age: { $gt: 25 } })
db.users.findOne({ email: "rahul@example.com" })db.users.updateOne(
{ _id: ObjectId("64a1b2c3d4e5f6a7b8c90001") },
{ $set: { isActive: false } }
)db.users.deleteOne({ _id: ObjectId("64a1b2c3d4e5f6a7b8c90001") })Also useful
- insertManyinsert several documents
- updateManyupdate every match
- deleteManydelete every match
- upsertinsert if no match
Query Operators
LearnComparison
`$in` on one field beats `$or` of equalities. `$or` across different fields needs an index per branch.
Projection
Learndb.users.find(
{ city: "Bangalore" },
{ name: 1, email: 1 }
)- 1include the field
- 0exclude the field
- _idreturned unless you set `_id: 0`
Do not mix include and exclude, except excluding `_id` on an include list. Projection can make a query covered.
Arrays & Nested Documents
Learn{ "address.city": "Bangalore" }{ skills: "Node.js" }{ skills: { $all: ["Node.js", "MongoDB"] } }{
skills: {
$elemMatch: {
name: "Node.js",
experience: { $gt: 2 }
}
}
}Dot notation on arrays of objects can match different elements. Use `$elemMatch` when one element must satisfy every condition.
Update Operators
LearnSorting & Pagination
Learndb.orders.find({ status: "completed" })
.sort({ createdAt: -1 })
.limit(10)
.skip(20)- 1 / -1ascending / descending
- Small datasetskip/limit can be fine
- Large datasetprefer cursor-based pagination
db.orders.find({ _id: { $gt: lastId } })
.sort({ _id: 1 })
.limit(10)`skip(n)` still walks n documents. Cost grows with page number. Interview takeaway: offset pagination does not scale.
Aggregation
Learn- Documents
- $match
- $group
- $sort
- $limit
- Result
Stages
db.orders.aggregate([
{ $match: { status: "completed" } },
{
$group: {
_id: "$userId",
totalSpent: { $sum: "$amount" }
}
},
{ $sort: { totalSpent: -1 } },
{ $limit: 3 }
])`$match` early. `$lookup` is a left outer join — index the foreign field, and do not use it as a default for every relationship.
Aggregation Expressions
LearnDate
- $yearyear
- $monthmonth
- $dayOfMonthday
- $dateToStringformat a date
Data Modeling
LearnEmbed when
- data is read together
- one-to-few
- child data is bounded
- you want a single-document read
Reference when
- data is large
- data is independently accessed
- relationship is many-to-many
- the relationship can grow without bound
- Embeddingfewer queries · data can duplicate · document can grow
- Referencingnormalized · extra queries / `$lookup` · independent documents
Start from the access pattern. Order `items` embed. A user's orders reference. Documents cap at 16MB.
Indexing
Learndb.users.createIndex({ email: 1 })db.orders.createIndex({ userId: 1, createdAt: -1 })db.users.createIndex({ email: 1 }, { unique: true })db.sessions.createIndex(
{ createdAt: 1 },
{ expireAfterSeconds: 3600 }
)Query Performance
Learn- explain()
- executionStats
db.orders.find({ status: "delivered" }).explain("executionStats")Prefer IXSCAN for selective queries. COLLSCAN is not automatically wrong — a tiny collection or a query that must read most documents can still scan. Judge the plan against the query and the dataset. Look at examined vs returned.
Atomicity & Transactions
Learn- One documentalready atomic
- Several documentstransaction may be required
session.startTransaction()
// operations
await session.commitTransaction()await session.abortTransaction()Transactions give atomicity across multiple operations. Use them when necessary — not as the default write path. Prefer a model where one document write is enough.
Concurrency
Learn- Atomic updatesafest when one document is enough
- Transactioncoordinate multiple operations
- Raceconcurrent ops produce incorrect state
// race
const product = await products.findOne({ _id })
await products.updateOne(
{ _id },
{ $set: { stock: product.stock - 1 } }
)
// atomic
await products.updateOne(
{ _id, stock: { $gt: 0 } },
{ $inc: { stock: -1 } }
)Node.js + MongoDB
Learnconst client = new MongoClient(MONGO_URI);
await client.connect();
const db = client.db("app");
const users = db.collection("users");
const user = await users.findOne({ email });Do not create a new MongoDB connection for every request. Reuse the MongoClient / connection pool.
Core objects
- MongoClientone client, one pool
- Database`client.db(name)`
- Collection`db.collection(name)`
- Connection poolowned by the client
- Env varsURI and credentials live here
Mongoose
LearnCommon methods
- find()cursor of documents
- findOne()one document or null
- create()insert via the model
- save()persist a document
- updateOne()update without loading
- findById()lookup by `_id`
- deleteOne()remove one
Worth remembering
- populate()follow refs
- lean()plain JS objects, no document overhead
- middlewarepre/post hooks
- validationschema rules before write
- indexesdeclared on the schema
- transactionssame sessions as the driver
Production MongoDB
Learn- Primary
- Secondaries
- Replica sethigh availability, failover, replication
- Shardinghorizontal scaling — data across shards
- Read preferencewhere reads are allowed to go
- Write concernhow much acknowledgement a write needs
- Read concernhow consistent a read must be
Security
LearnDo
- store credentials in environment variables
- validate user input before it becomes a query
- restrict network access
- use least-privilege database roles
- protect connection strings
Don't
- commit secrets or `.env` files
- expose the database to the public internet
- give an app user cluster-admin
- build queries from raw request bodies
Common Mistakes
Learn✕No indexes on frequently queried fields
→Index the equality and sort fields your hot queries actually use. Learn
✕Too many indexes
→Every index costs writes and RAM. Drop unused ones. Learn
✕Using skip() for massive pagination
→Use a cursor on `_id` or a unique sorted field. Learn
✕Unbounded arrays
→Reference or bucket once the array can grow without a cap. Learn
✕Returning huge documents
→Project the fields the caller needs. Learn
✕Overusing $lookup
→Embed data that is always read together; lookup is not a default join. Learn
✕Treating flexible schema as “no schema”
→The schema still lives somewhere — usually in application code or validators. Learn
✕Creating a new DB connection per request
→Reuse one MongoClient and its pool. Learn
✕Using transactions unnecessarily
→Model so a single-document write is the common case. Learn
✕Passing a string instead of ObjectId
→Cast with `new ObjectId(id)` (or let Mongoose do it). Learn
✕Not checking explain()
→Read executionStats before guessing an index. Learn
Interview Quick Revision
LearnMongoDB is document-oriented with a flexible document model. SQL is relational with a structured schema.
Embed when data belongs together and is bounded. Reference when it is independent, large, or unbounded.
Faster reads, paid for with storage and write overhead.
A pipeline of stages that transforms documents.
Useful when multiple operations must succeed or fail together.
High availability and failover.
Horizontal scaling by distributing data across shards.
All conditions must hold on the same array element.
Equality fields, then sort, then range.