Ultimate MongoDB Commands Cheat Sheet: NoSQL Database Operations and Queries

Ultimate MongoDB Commands Cheat Sheet

I switched between relational and document databases enough times over the years that I finally got tired of googling the same MongoDB syntax over and over. So I built this cheat sheet the way I actually use MongoDB day to day — from spinning up a local instance, to writing aggregation pipelines, to locking down a production cluster with proper authentication.

If you’re building a Node.js API, prototyping fast, or just trying to get comfortable with document-based data modeling, this is meant to be the single page you keep open. I’ve tried to cover the commands you’ll type constantly and the ones you’ll only need once a year but always forget.

Let’s dive in.

Table of Contents

  1. Getting Started: Connecting to MongoDB
  2. Database and Collection Management
  3. Data Types in MongoDB
  4. CRUD Operations: Insert, Find, Update, Delete
  5. Query Operators Reference
  6. Sorting, Limiting, and Pagination
  7. The Aggregation Framework
  8. Indexes and Performance
  9. Schema Design and Data Modeling
  10. Transactions
  11. User Management and Security
  12. Backup and Restore
  13. Replication and Sharding Basics
  14. Troubleshooting Common Errors
  15. Best Practices
  16. Real-World Use Cases
  17. Frequently Asked Questions
  18. Common Mistakes to Avoid
  19. Interview Questions
  20. Printable Quick-Reference Summary
  21. Official Documentation Links

1. Getting Started: Connecting to MongoDB

I mostly use the mongosh shell (the modern replacement for the legacy mongo shell) for quick checks, and a driver in application code for everything else.

# Connect to a local instance
mongosh

# Connect to a specific host and port
mongosh --host 127.0.0.1 --port 27017

# Connect with authentication
mongosh "mongodb://username:password@localhost:27017/mydb"

# Connect to MongoDB Atlas (cloud)
mongosh "mongodb+srv://cluster0.mongodb.net/mydb" --username myuser

Once inside the shell:

// Show current database
db

// List all databases
show dbs

// Switch to (or create) a database
use myapp

// Show current server status
db.serverStatus()

// Show MongoDB version
db.version()

One thing that catches newcomers off guard: use myapp doesn’t actually create the database until you insert data into a collection. MongoDB creates databases and collections lazily, on first write.


2. Database and Collection Management

TaskCommand
List databasesshow dbs
Switch/create databaseuse dbname
Show current databasedb
Drop current databasedb.dropDatabase()
List collectionsshow collections
Create a collection explicitlydb.createCollection("users")
Drop a collectiondb.users.drop()
Rename a collectiondb.users.renameCollection("app_users")
Get collection statsdb.users.stats()
// Create a collection with schema validation
db.createCollection("users", {
  validator: {
    $jsonSchema: {
      bsonType: "object",
      required: ["username", "email"],
      properties: {
        username: { bsonType: "string" },
        email: { bsonType: "string", pattern: "^.+@.+$" },
        age: { bsonType: "int", minimum: 0 }
      }
    }
  }
})

I use schema validation on any collection where I want MongoDB’s flexibility but still need some guardrails — it’s saved me from bad data creeping in during early development when I was still iterating on the app’s models.


3. Data Types in MongoDB

MongoDB stores data as BSON (Binary JSON), which supports more types than plain JSON.

TypeExampleNotes
String"hello"UTF-8
Number (Int32)NumberInt(42)32-bit integer
Number (Int64)NumberLong(42)64-bit integer
Double42.5Default number type
Decimal128NumberDecimal("42.50")For precise decimal math (currency)
Booleantrue / false
DateISODate("2024-01-01")Stored as UTC
Array["a", "b", "c"]Ordered list
Object{ street: "Main St" }Embedded document
ObjectIdObjectId("64f...")Default _id type, 12-byte unique ID
Nullnull
Binary DataBinData(...)For files, hashes, etc.
// Every document gets a unique _id automatically if not provided
db.users.insertOne({ username: "johndoe" })
// _id: ObjectId("...") is generated automatically

I default to Decimal128 for any money field, the same way I’d use DECIMAL in a relational database — floating point rounding errors are just as real here.


4. CRUD Operations: Insert, Find, Update, Delete

Insert

// Insert a single document
db.users.insertOne({
  username: "johndoe",
  email: "john@example.com",
  age: 29,
  createdAt: new Date()
})

// Insert multiple documents
db.users.insertMany([
  { username: "alice", email: "alice@example.com" },
  { username: "bob", email: "bob@example.com" }
])

Expected output:

{
  acknowledged: true,
  insertedId: ObjectId("64f1a2b3c4d5e6f7a8b9c0d1")
}

Find

// Find all documents
db.users.find()

// Find with a filter
db.users.find({ username: "johndoe" })

// Find one document
db.users.findOne({ email: "john@example.com" })

// Find with projection (return only specific fields)
db.users.find({}, { username: 1, email: 1, _id: 0 })

// Pretty-print results in the shell
db.users.find().pretty()

Update

// Update a single document
db.users.updateOne(
  { username: "johndoe" },
  { $set: { email: "newemail@example.com" } }
)

// Update multiple documents
db.users.updateMany(
  { status: "inactive" },
  { $set: { status: "archived" } }
)

// Upsert (insert if not found)
db.users.updateOne(
  { username: "newuser" },
  { $set: { email: "new@example.com" } },
  { upsert: true }
)

// Replace an entire document
db.users.replaceOne(
  { username: "johndoe" },
  { username: "johndoe", email: "john@newdomain.com" }
)

Delete

// Delete a single document
db.users.deleteOne({ username: "johndoe" })

// Delete multiple documents
db.users.deleteMany({ status: "archived" })

// Delete all documents in a collection (keeps the collection itself)
db.users.deleteMany({})

Same rule as any database: I always run the equivalent find() with the same filter before running deleteMany() or updateMany(), just to see exactly what I’m about to touch.


5. Query Operators Reference

OperatorMeaningExample
$eqEquals{ age: { $eq: 30 } }
$neNot equals{ age: { $ne: 30 } }
$gt / $gteGreater than / or equal{ age: { $gt: 18 } }
$lt / $lteLess than / or equal{ age: { $lt: 65 } }
$inMatches any value in array{ status: { $in: ["active", "pending"] } }
$ninMatches none of the values{ status: { $nin: ["banned"] } }
$andLogical AND{ $and: [{ age: { $gt: 18 } }, { status: "active" }] }
$orLogical OR{ $or: [{ status: "active" }, { vip: true }] }
$notNegates a condition{ age: { $not: { $lt: 18 } } }
$existsField presence check{ phone: { $exists: true } }
$regexPattern matching{ email: { $regex: "@gmail.com$" } }
$elemMatchArray element matches condition{ scores: { $elemMatch: { $gt: 80 } } }
$sizeArray length{ tags: { $size: 3 } }
$allArray contains all values{ tags: { $all: ["mongo", "db"] } }
// Combining operators
db.orders.find({
  status: { $in: ["shipped", "delivered"] },
  total: { $gte: 50, $lte: 500 }
})

// Nested field query
db.users.find({ "address.city": "New York" })

6. Sorting, Limiting, and Pagination

// Sort ascending (1) or descending (-1)
db.users.find().sort({ createdAt: -1 })

// Limit results
db.users.find().limit(10)

// Skip for pagination
db.users.find().skip(20).limit(10)

// Count matching documents
db.users.countDocuments({ status: "active" })

// Combine sort, skip, and limit for a paginated query
db.orders.find({ status: "shipped" })
  .sort({ createdAt: -1 })
  .skip(0)
  .limit(25)

For large collections, I avoid skip() on deep pagination since it gets slower the further you page — I switch to cursor-based pagination using _id or a timestamp instead once a collection gets large.


7. The Aggregation Framework

This is where MongoDB really earns its keep for analytics-style queries. Think of it as a pipeline — each stage transforms the data and passes it to the next.

// Basic aggregation: total spent per user
db.orders.aggregate([
  { $match: { status: "completed" } },
  { $group: { _id: "$userId", totalSpent: { $sum: "$total" } } },
  { $sort: { totalSpent: -1 } },
  { $limit: 10 }
])

// $project to reshape output
db.users.aggregate([
  { $project: { username: 1, email: 1, fullName: { $concat: ["$firstName", " ", "$lastName"] } } }
])

// $lookup — the MongoDB equivalent of a SQL join
db.orders.aggregate([
  {
    $lookup: {
      from: "users",
      localField: "userId",
      foreignField: "_id",
      as: "userDetails"
    }
  },
  { $unwind: "$userDetails" }
])

// $unwind — flatten an array field into separate documents
db.orders.aggregate([
  { $unwind: "$items" },
  { $group: { _id: "$items.productId", totalSold: { $sum: "$items.quantity" } } }
])

// $facet — run multiple aggregation pipelines in parallel
db.products.aggregate([
  {
    $facet: {
      byCategory: [{ $group: { _id: "$category", count: { $sum: 1 } } }],
      priceStats: [{ $group: { _id: null, avgPrice: { $avg: "$price" } } }]
    }
  }
])

I use $lookup constantly to replicate join-style reporting, and $facet whenever I want to build a dashboard summary in a single round trip instead of firing off five separate queries.


8. Indexes and Performance

// Create a single-field index
db.users.createIndex({ email: 1 })

// Create a unique index
db.users.createIndex({ email: 1 }, { unique: true })

// Compound index
db.orders.createIndex({ status: 1, createdAt: -1 })

// Text index for search
db.articles.createIndex({ content: "text" })

// TTL index — automatically expire documents (great for sessions/logs)
db.sessions.createIndex({ createdAt: 1 }, { expireAfterSeconds: 3600 })

// List indexes on a collection
db.users.getIndexes()

// Drop an index
db.users.dropIndex("email_1")

// Analyze query performance
db.users.find({ email: "john@example.com" }).explain("executionStats")

Same rule of thumb as any database: index the fields you filter, sort, and join on. TTL indexes in particular are one of my favorite MongoDB features — I’ve used them for session storage and rate-limit tracking without needing a separate cron job to clean up expired data.


9. Schema Design and Data Modeling

MongoDB gives you two main modeling strategies, and picking the right one per relationship matters a lot.

Embedding (nesting related data inside a document):

{
  _id: ObjectId("..."),
  username: "johndoe",
  address: {
    street: "123 Main St",
    city: "New York",
    zip: "10001"
  }
}

Good for data that’s always accessed together and doesn’t grow unbounded — like a user’s address or profile settings.

Referencing (storing an ID and looking it up separately):

// users collection
{ _id: ObjectId("user1"), username: "johndoe" }

// orders collection
{ _id: ObjectId("order1"), userId: ObjectId("user1"), total: 99.99 }

Better for data that grows large or is shared across many documents — like a user’s order history, which could have thousands of entries.

My general rule: embed when the relationship is one-to-few and the nested data is always read together with the parent. Reference when the relationship is one-to-many at scale, or many-to-many.


10. Transactions

MongoDB has supported multi-document ACID transactions since version 4.0, which changed how I think about it for financial or multi-step operations.

const session = db.getMongo().startSession()
session.startTransaction()

try {
  const users = session.getDatabase("myapp").users
  const accounts = session.getDatabase("myapp").accounts

  users.updateOne({ _id: userId }, { $inc: { balance: -100 } })
  accounts.updateOne({ _id: accountId }, { $inc: { balance: 100 } })

  session.commitTransaction()
} catch (error) {
  session.abortTransaction()
  throw error
} finally {
  session.endSession()
}

For a single document, updates are always atomic by default in MongoDB, so you often don’t need a full transaction. I reach for explicit transactions only when I’m touching multiple documents or multiple collections that need to succeed or fail together.


11. User Management and Security

// Create an admin user (run from the admin database)
use admin
db.createUser({
  user: "adminUser",
  pwd: "StrongPassword123!",
  roles: [{ role: "userAdminAnyDatabase", db: "admin" }]
})

// Create an application-specific user with limited privileges
use myapp
db.createUser({
  user: "appUser",
  pwd: "AnotherStrongPassword456!",
  roles: [{ role: "readWrite", db: "myapp" }]
})

// List users
db.getUsers()

// Update a user's roles
db.updateUser("appUser", { roles: [{ role: "read", db: "myapp" }] })

// Drop a user
db.dropUser("appUser")

// Show current user's roles
db.runCommand({ connectionStatus: 1 })

Security tips I follow on every project:

  • Enable authentication (--auth or security.authorization: enabled in the config file) — MongoDB doesn’t require auth by default on a fresh local install, which is a common cause of exposed databases.
  • Use role-based access control and give each application user only the roles it needs (read, readWrite, not dbOwner unless truly necessary).
  • Never expose MongoDB directly to the public internet without a firewall, VPN, or IP allowlist.
  • Enable TLS/SSL for connections in production.
  • Sanitize and validate all user input in application code — MongoDB queries built from unsanitized input can still be vulnerable to injection-style attacks (e.g., passing an object where a string is expected).
  • Rotate credentials and audit db.getUsers() periodically.

12. Backup and Restore

# Backup an entire database
mongodump --db myapp --out /backup/2024-01-01

# Backup a specific collection
mongodump --db myapp --collection users --out /backup/2024-01-01

# Restore a database
mongorestore --db myapp /backup/2024-01-01/myapp

# Backup with authentication
mongodump --uri="mongodb://user:pass@localhost:27017/myapp" --out /backup

# Export a collection to JSON
mongoexport --db myapp --collection users --out users.json

# Import a collection from JSON
mongoimport --db myapp --collection users --file users.json

For production systems, I pair mongodump snapshots with MongoDB Atlas’s continuous backup feature (or replica set oplog-based backups if self-hosted) so I can do point-in-time recovery rather than relying only on daily dumps.


13. Replication and Sharding Basics

// Initiate a replica set
rs.initiate({
  _id: "rs0",
  members: [
    { _id: 0, host: "localhost:27017" },
    { _id: 1, host: "localhost:27018" },
    { _id: 2, host: "localhost:27019" }
  ]
})

// Check replica set status
rs.status()

// Check which node is primary
rs.isMaster()

// Enable sharding on a database
sh.enableSharding("myapp")

// Shard a collection on a chosen key
sh.shardCollection("myapp.orders", { userId: 1 })

// Check sharding status
sh.status()

I’ve only needed sharding on a handful of projects that hit real scale, but replica sets I consider close to mandatory for any production deployment — they’re what give you automatic failover if the primary node goes down.


14. Troubleshooting Common Errors

ErrorLikely CauseFix
MongoServerError: Authentication failedWrong username/password or wrong auth databaseConfirm credentials and the authSource parameter in the connection string
MongoNetworkError: connect ECONNREFUSEDMongoDB service isn’t running or wrong host/portCheck mongod is running, verify host and port
E11000 duplicate key errorViolates a unique indexCheck existing documents or use upsert logic intentionally
BSONObjectTooLargeDocument exceeds 16MB limitSplit large data across multiple documents or use GridFS for files
not primary and slaveOk=falseWriting to a secondary node in a replica setEnsure writes go to the primary, or check connection settings
Query exceeded time limitMissing index or overly broad query on a large collectionRun .explain() and add an appropriate index
WiredTiger error on startupCorrupted data files, often from an unclean shutdownRestore from backup or run repair (mongod --repair) as a last resort
// Check current operations (useful for stuck queries)
db.currentOp()

// Kill a specific operation
db.killOp(12345)

// Check server logs for recent issues
db.adminCommand({ getLog: "global" })

15. Best Practices

  • Design your schema around your query patterns, not around normalization habits carried over from relational databases.
  • Keep documents under a few hundred KB when possible — even though the hard limit is 16MB, huge documents hurt read/write performance.
  • Use indexes deliberately; check .explain() before assuming a query needs one.
  • Prefer updateOne/updateMany with $set over full document replacement to avoid accidentally wiping fields.
  • Use schema validation on collections where data consistency matters, even though MongoDB doesn’t require a fixed schema.
  • Always specify a projection in production find() queries instead of returning entire documents by default.
  • Use connection pooling in your driver instead of opening a new connection per request.
  • Enable authentication and access control from day one, even in development, so it’s not an afterthought before launch.

16. Real-World Use Cases

Product catalogs: MongoDB’s flexible schema has been genuinely useful for e-commerce catalogs where different product categories have wildly different attributes — a laptop has different specs than a t-shirt, and forcing that into a rigid relational schema always felt clunky.

Real-time analytics dashboards: I’ve built dashboards using the aggregation framework’s $facet and $group stages to compute multiple summary statistics in a single query instead of hitting the database repeatedly.

Session and cache storage: TTL indexes make MongoDB a solid fit for storing user sessions or short-lived tokens that need to expire automatically.

Content management systems: Embedding comments, tags, and metadata directly inside article documents has made read performance excellent for content-heavy applications where writes are far less frequent than reads.


17. Frequently Asked Questions

Is MongoDB schema-less? Not entirely — it’s schema-flexible. You can enforce structure with $jsonSchema validation, but by default, documents in the same collection can have different fields.

What’s the difference between updateOne and findOneAndUpdate? updateOne returns a write result (matched/modified counts). findOneAndUpdate returns the actual document (before or after the update, depending on options), which is useful when you need the updated data immediately.

How do I find duplicate values in a field?

db.users.aggregate([
  { $group: { _id: "$email", count: { $sum: 1 } } },
  { $match: { count: { $gt: 1 } } }
])

How do I copy a collection?

db.users.aggregate([{ $match: {} }, { $out: "users_copy" }])

What happens if I query a field that doesn’t exist on some documents? MongoDB simply treats it as null/non-existent for that document — it won’t error out, which is both a strength and a source of subtle bugs if you’re not careful with $exists checks.

Is MongoDB ACID-compliant? Single-document operations are always atomic. Multi-document ACID transactions are supported since version 4.0 for replica sets, and since 4.2 for sharded clusters.

How is _id different from a normal field? _id is required, automatically indexed, and unique per collection. If you don’t provide one on insert, MongoDB generates an ObjectId for you.


18. Common Mistakes to Avoid

  • Running deleteMany({}) or updateMany({}, ...) without double-checking the filter first.
  • Treating MongoDB like a relational database and over-normalizing data into too many collections with excessive $lookup joins.
  • Ignoring the 16MB document size limit until it becomes a production incident.
  • Not creating indexes for frequently queried fields, then wondering why queries are slow at scale.
  • Using skip() for deep pagination on large collections instead of cursor-based pagination.
  • Storing large binary files directly in documents instead of using GridFS or external object storage.
  • Leaving authentication disabled on a development instance that later gets exposed accidentally.
  • Forgetting that array updates with $push can grow a document unbounded over time if there’s no cap or archiving strategy.

19. Interview Questions

  1. What’s the difference between embedding and referencing in MongoDB schema design?
  2. Explain how the aggregation pipeline works and name three common stages.
  3. What is an ObjectId, and what information is encoded in it?
  4. How does MongoDB handle transactions, and when did multi-document ACID transactions become available?
  5. What’s the difference between $lookup and a SQL JOIN?
  6. How do TTL indexes work, and where would you use one?
  7. What’s the maximum document size in MongoDB, and how would you handle larger data?
  8. Explain the difference between a replica set and a sharded cluster.
  9. How would you design a schema for a one-to-many relationship with millions of “many” records?
  10. What’s the difference between find() and aggregate()?
  11. How does MongoDB achieve high availability?
  12. What are the trade-offs of using an unstructured/dynamic schema?

20. Printable Quick-Reference Summary

DATABASES        show dbs; use dbname; db.dropDatabase();
COLLECTIONS      show collections; db.createCollection(); db.coll.drop();
INSERT           db.coll.insertOne({...}); db.coll.insertMany([...]);
FIND             db.coll.find({filter}); db.coll.findOne({filter});
UPDATE           db.coll.updateOne(filter, { $set: {...} });
DELETE           db.coll.deleteOne(filter); db.coll.deleteMany(filter);
OPERATORS        $eq $ne $gt $gte $lt $lte $in $nin $and $or $exists $regex
SORT/LIMIT       .sort({field:1/-1}).skip(n).limit(n)
AGGREGATE        db.coll.aggregate([{$match},{$group},{$sort},{$lookup}])
INDEXES          db.coll.createIndex({field:1}); db.coll.getIndexes();
TRANSACTIONS     session.startTransaction(); session.commitTransaction();
USERS            db.createUser({...}); db.getUsers(); db.dropUser();
BACKUP           mongodump --db name --out /path
RESTORE          mongorestore --db name /path/name

Print this section out or pin it to a second monitor — it covers the commands that make up the bulk of daily MongoDB work.


21. Official Documentation Links

  • MongoDB Manual: https://www.mongodb.com/docs/manual/
  • MongoDB Aggregation Pipeline Reference: https://www.mongodb.com/docs/manual/core/aggregation-pipeline/
  • MongoDB Query Operators: https://www.mongodb.com/docs/manual/reference/operator/query/
  • mongodump / mongorestore Docs: https://www.mongodb.com/docs/database-tools/mongodump/
  • MongoDB Security Checklist: https://www.mongodb.com/docs/manual/administration/security-checklist/

I revisit this sheet every time MongoDB ships a new major version, because the aggregation framework in particular keeps getting new operators worth knowing. Bookmark it, and it’ll stay useful well past today.

Total
3
Shares

Leave a Reply

Previous Post
Ultimate Linux Commands Cheat Sheet

Ultimate Linux Commands Cheat Sheet: Essential Terminal Commands for Power Users

Next Post
Ultimate MySQL Commands Cheat Sheet

Ultimate MySQL Commands Cheat Sheet: Database Management and Query Reference

Related Posts