MongoDB Cheatsheet - MongoDB Command Reference
For backend developers using a document store where reads must stay fast. MongoDB shines at schemaless flexible documents, but that freedom costs you unless you index the fields you filter on. By the end you can design CRUD queries against a collection, read explain("executionStats") to confirm an index is used, build an aggregation pipeline with match/group/sort, and know what a replica set guarantees versus what requires sharding.
Typical Use Case
For developers using MongoDB as their datastore. This sheet covers database and collection operations, document CRUD, query operators, index management, the aggregation pipeline, and replication and sharding. The two points that actually decide production performance are called out explicitly: how query operators are used ($gt, $in and friends, so you filter in the database rather than in memory), and index creation, since an unindexed query on a large collection is a full collection scan. Read the aggregation section closely too — $match placed first and $project used early cut data volume dramatically.
Database 6
show dbsuse dbnamedbdb.stats()db.dropDatabase()show collectionsDocument CRUD 9
db.collection.insertOne({name: "tom"})db.collection.insertMany([{...}, {...}])db.collection.find()db.collection.find({age: {$gt: 18}})db.collection.findOne({name: "tom"})db.collection.updateOne({name: "tom"}, {$set: {age: 20}})db.collection.updateMany({age: {$lt: 18}}, {$set: {status: "minor"}})db.collection.deleteOne({name: "tom"})db.collection.deleteMany({age: {$lt: 18}})Query Operators 8
{field: value}{field: {$gt: value}}{field: {$lt: value}}{field: {$ne: value}}{field: {$in: [v1, v2]}}{$and: [{...}, {...}]}{$or: [{...}, {...}]}{field: /regex/i}Index 6
db.collection.createIndex({field: 1})db.collection.createIndex({f1: 1, f2: 1})db.collection.createIndex({field: 1}, {unique: true})db.collection.createIndex({field: 1}, {expireAfterSeconds: 3600})db.collection.getIndexes()db.collection.dropIndex("index_name")Aggregation 7
db.collection.aggregate([{$match: {age: {$gt: 18}}}]){$group: {_id: "$field", count: {$sum: 1}}}{$project: {name: 1, _id: 0}}{$sort: {field: -1}}{$limit: 10} / {$skip: 20}{$unwind: "$arrayField"}{$lookup: {from: "other", localField: "id", foreignField: "_id", as: "joined"}}Replication & Sharding 7
rs.status()rs.conf()rs.initiate()rs.add("host:port")rs.remove("host:port")sh.status()sh.enableSharding("dbname")Parameter matrix
| Parameter | Effect | Example |
|---|---|---|
use dbname | Switches database (creates it automatically if missing). | use dbname |
show dbs / show collections | Lists databases / the collections of the current database. | show collections |
insertOne / insertMany | Inserts a single document / a batch. | db.c.insertMany([{...}]) |
findOne / find | Queries a single document / all. | db.c.find({age: {$gt: 18}}) |
$gt / $gte / $lt / $lte | Comparison operators. | {age: {$gte: 18}} |
$ne / $in | Not equal / in a list. | {_id: {$in: [1, 2]}} |
$and / $or | Logical and / or. | {$or: [{a: 1}, {b: 2}]} |
/regex/i | Regex match (i ignores case). | {name: /tom/i} |
updateOne / updateMany | Updates a single document / a batch, paired with $set. | db.c.updateMany({}, {$set: {st: "ok"}}) |
compound createIndex | Multi-field index; field order affects efficiency. | db.c.createIndex({f1: 1, f2: 1}) |
unique: true | Unique index; duplicate inserts error out. | db.c.createIndex({email: 1}, {unique: true}) |
expireAfterSeconds | TTL index; documents are deleted automatically on expiry. | db.c.createIndex({ts: 1}, {expireAfterSeconds: 3600}) |
$group / $project | Group aggregation / field projection. | {$group: {_id: "$city", n: {$sum: 1}}} |
$unwind / $lookup | Unwind an array / join across collections. | {$lookup: {from: "b", localField: "id", as: "j"}} |
Common pitfalls
SymptomQueries on a large collection are extremely slow and explain shows COLLSCAN.
CauseThe query field has no index and MongoDB does a full collection scan.
FixConfirm indexes with db.collection.getIndexes() and createIndex on high-frequency query fields; then use explain("executionStats") to check whether it uses IXSCAN.
SymptomAfter updateMany some fields are overwritten to null.
CauseReplacement and update semantics got mixed; assigning a whole object drops fields you did not mention.
FixAlways pair with $set to write only the fields you mean to change; keys outside $set are not deleted.
SymptomQuerying an array field with $in does not return the expected results.
Cause$in on an array field means "matches if it contains any element", not an exact match element by element.
FixUse $all when the array must contain all elements; use a direct field value for an exact match.
SymptomInserts raise a duplicate key error even though the data clearly has no duplicate values.
CauseA unique index already exists, and the duplicate check is on the index field rather than _id.
FixUse getIndexes() to find the unique index and check the actual values of its fields; an index built on the wrong field also causes false errors.
SymptomThe collection size explodes and the disk fills up.
CauseNo TTL index is set, so log-like documents are kept forever.
FixCreate an expireAfterSeconds index on the timestamp field; use db.stats() to confirm actual usage.
SymptomThe aggregation pipeline runs very slowly and throws an out-of-memory error.
Cause$sort and $group consume a lot of memory on large collections, and allowDiskUse is off.
FixPut $match first in the pipeline to shrink the data; set allowDiskUse: true when needed; confirm the sort field is indexed.
SymptomAfter using a non-existent database it shows up in show dbs.
Causeuse creates a non-existent database immediately.
FixAfter an accidental creation, drop it with db.dropDatabase(); to just view the list, do not use a name that does not exist.
Troubleshooting
1Check whether the query actually uses an index.
db.collection.find({age: {$gt: 18}}).explain("executionStats")In winningPlan, note whether it is IXSCAN or COLLSCAN, and the totalDocsExamined value.
2Confirm the indexes on the collection.
db.collection.getIndexes()The first step in debugging a slow query: whether the query field is indexed and whether the index is unique.
3Group and count by field.
db.collection.aggregate([{$group: {_id: "$city", n: {$sum: 1}}}])Putting $match first in the pipeline significantly reduces the data entering $group.
4Auto-expire stale data with a TTL index.
db.logs.createIndex({createdAt: 1}, {expireAfterSeconds: 2592000})expireAfterSeconds is in seconds; the field must be of BSON Date type.
5Confirm the actual database usage.
db.stats()Includes dataSize and indexSize, pinpointing whether disk usage is data or index.
Command Examples
Index before querying, or it slows as data grows
db.orders.createIndex({ customerId: 1, createdAt: -1 })
db.orders.find({ customerId: 'c_1024' }).sort({ createdAt: -1 }).limit(20)A compound index follows the leftmost-prefix rule: only conditions starting with customerId can match. Order the fields by the real query pattern, with frequently queried fields first.
Output
createdAt_-1_customerId_1
{ "customerId" : 1, "createdAt" : -1 }
{ "orderId" : "o_8821", "total" : 199.0 }Aggregation pipeline: put $match first
db.orders.aggregate([
{ $match: { status: "paid", createdAt: { $gte: ISODate("2026-09-01") } } },
{ $group: { _id: "$customerId", total: { $sum: "$amount" }, n: { $sum: 1 } } },
{ $sort: { total: -1 } },
{ $limit: 10 }
])The pipeline runs in order; putting $match first shrinks the data so the cost of later $group/$sort drops accordingly. This is the most important rule of aggregation performance.
Output
{ "_id" : "c_1024", "total" : 1842.5, "n" : 12 }
{ "_id" : "c_2087", "total" : 1204.0, "n" : 7 }TTL index for automatic cleanup
db.sessions.createIndex({ createdAt: 1 }, { expireAfterSeconds: 3600 })Suits logs and sessions; MongoDB deletes documents automatically after expiry, saving a cleanup job. Note it runs on a background cycle, so deletion is delayed rather than punctual.
Output
createdAt_1
Common Pitfalls
- An unindexed query is a full collection scan that collapses as data grows — verify indexes exist before going live.
- Compound indexes follow the leftmost-prefix rule, so field order must match real query patterns or the index is wasted.
- Legacy APIs such as db.collection.remove() are deprecated; use deleteMany / deleteOne.
- TTL deletion runs asynchronously, so expired documents do not vanish immediately and cannot be used for precise point-in-time cleanup.
- estimatedDocumentCount reads metadata and is fast but can be inaccurate while transactions are in flight; use countDocuments when exactness matters.
- Sorting on an unindexed field with a large skip degrades to a full scan — paginate with a cursor instead.
Tips
- MongoDB has no fixed schema by default, but use an ORM like Mongoose for validation.
- Avoid full collection scans — index large collections and use explain() to inspect the plan.
- Use at least 3 replica-set nodes for HA; an odd count avoids split-brain.
FAQ
What should I do first when a MongoDB query is slow?
Confirm the filter fields are indexed by checking db.collection.getIndexes(). The flexibility of a document database has a cost: an unindexed query is a full collection scan, which collapses in performance once data grows. Compound indexes follow the leftmost-prefix rule — createIndex({f1: 1, f2: 1}) only accelerates queries whose leading predicate is on f1 — so order fields according to real query patterns.
What does a TTL index do?
db.collection.createIndex({field: 1}, {expireAfterSeconds: 3600}) indexes the field for expiry; when its value is a date or timestamp, MongoDB removes the document once it passes. Logs and sessions are the typical uses — a TTL index on created_at cleans up without a separate maintenance job. Note that deletion runs on a background cycle, so it is delayed rather than instantaneous.
countDocuments versus estimatedDocumentCount?
estimatedDocumentCount reads collection metadata, so it is extremely fast but can be inaccurate while transactions are still committing. countDocuments actually scans and counts, which is slower but reliable. Use countDocuments when accuracy matters and the estimate only to decide whether continuing is worthwhile. Batch jobs often want both: estimate to triage, exact count to verify.
When should I use an aggregation pipeline versus a plain query?
Use find for simple filtering and sorting, where indexes apply directly. Reach for aggregate when you need grouped counts, field transformations or multi-stage processing — it runs stages in order: $match, $group, $project, $sort, $limit. The key optimization is to put $match first so later stages work on a smaller set.
How does a TTL index differ from an ordinary index?
An ordinary index only speeds up lookups. A TTL index does that too but additionally deletes documents once they expire, delegating cleanup to the database. A unique index, created with {unique: true}, prevents duplicate values. All three compose: a session collection can be simultaneously unique and self-expiring.
Official References
Each command links to its official documentation below, so you can verify the latest usage and read deeper.
Maintained by LaoHand
Publicly updated on Jul 21, 2026, continuously proofread against official docs.
Contact Us
Wrong command or description? Send us corrections, business inquiries or product feedback by email.
Contact Us