MongoDB Cheatsheet
MongoDB is a NoSQL document database that stores data in flexible JSON-like documents. Perfect for applications that need flexible schemas and easy scaling.
Getting Started
What is MongoDB?
MongoDB stores data as documents (similar to JSON objects) instead of tables. This flexibility lets you:
- Store nested data easily
- Change structure without migrations
- Scale horizontally across servers
Installation & Setup
# Install MongoDB locally (macOS)
brew tap mongodb/brew
brew install mongodb-community
# Start MongoDB
brew services start mongodb-community
# Or install MongoDB Atlas (cloud)
# Visit: https://www.mongodb.com/cloud/atlas
# Install MongoDB Driver for Node.js
npm install mongodbConnect to MongoDB
const { MongoClient } = require('mongodb');
const uri = 'mongodb://localhost:27017';
const client = new MongoClient(uri);
async function connect() {
try {
await client.connect();
const db = client.db('myDatabase');
console.log('Connected to MongoDB');
return db;
} catch (error) {
console.error('Connection failed:', error);
}
}Database Operations (CRUD)
Create (Insert Documents)
const db = client.db('myDatabase');
const users = db.collection('users');
// Insert one document
await users.insertOne({
name: 'Alice',
email: 'alice@example.com',
age: 25,
createdAt: new Date()
});
// Insert many documents
await users.insertMany([
{ name: 'Bob', email: 'bob@example.com', age: 30 },
{ name: 'Charlie', email: 'charlie@example.com', age: 28 }
]);Read (Find Documents)
const users = db.collection('users');
// Find all documents
const allUsers = await users.find({}).toArray();
// Find one document
const user = await users.findOne({ email: 'alice@example.com' });
// Find with conditions
const adults = await users.find({ age: { $gte: 18 } }).toArray();
// Find specific fields (projection)
const names = await users
.find({})
.project({ name: 1, email: 1, _id: 0 })
.toArray();
// Limit and skip
const page = await users
.find({})
.skip(10)
.limit(5)
.toArray();Update Documents
const users = db.collection('users');
// Update one document
await users.updateOne(
{ email: 'alice@example.com' },
{ $set: { age: 26, updated: new Date() } }
);
// Update many documents
await users.updateMany(
{ age: { $lt: 18 } },
{ $set: { status: 'minor' } }
);
// Increment a field
await users.updateOne(
{ email: 'alice@example.com' },
{ $inc: { loginCount: 1 } }
);
// Push to array
await users.updateOne(
{ email: 'alice@example.com' },
{ $push: { tags: 'vip' } }
);Delete Documents
const users = db.collection('users');
// Delete one document
await users.deleteOne({ email: 'alice@example.com' });
// Delete many documents
await users.deleteMany({ age: { $lt: 18 } });
// Delete all documents
await users.deleteMany({});Query Operators
Comparison Operators
// Equal
{ age: 25 }
// Not equal
{ age: { $ne: 25 } }
// Greater than
{ age: { $gt: 18 } }
// Greater than or equal
{ age: { $gte: 18 } }
// Less than
{ age: { $lt: 65 } }
// Less than or equal
{ age: { $lte: 65 } }
// In array
{ status: { $in: ['active', 'pending'] } }
// Not in array
{ status: { $nin: ['deleted', 'banned'] } }Logical Operators
// AND (default - all conditions must match)
{ age: { $gt: 18 }, status: 'active' }
// OR (at least one condition matches)
{ $or: [{ age: { $lt: 18 } }, { status: 'suspended' }] }
// NOT
{ age: { $not: { $gt: 65 } } }
// NOR (neither condition matches)
{ $nor: [{ status: 'banned' }, { balance: { $lt: 0 } }] }Array Operators
// Element exists in array
{ tags: 'javascript' }
// Array contains element at index
{ 'tags.0': 'javascript' }
// Array size
{ tags: { $size: 3 } }
// Element in array that matches condition
{ scores: { $elemMatch: { $gt: 80, $lt: 100 } } }
// All elements match condition
{ scores: { $all: [80, 90] } }String Operators
// Regular expression match
{ email: { $regex: '^alice' } }
// Case-insensitive regex
{ email: { $regex: 'alice', $options: 'i' } }
// String contains
{ name: { $regex: 'Ali' } }Aggregation Pipeline (🟡 Intermediate)
Aggregation processes documents through stages to compute results.
const users = db.collection('users');
// Simple aggregation
const result = await users.aggregate([
// Stage 1: Filter
{ $match: { age: { $gte: 18 } } },
// Stage 2: Transform
{ $project: { name: 1, email: 1, ageGroup: { $cond: [{$gte: ['$age', 65]}, 'senior', 'adult']} } },
// Stage 3: Sort
{ $sort: { name: 1 } }
]).toArray();Common Pipeline Stages
// $match - Filter documents
{ $match: { status: 'active' } }
// $project - Select/transform fields
{ $project: { name: 1, email: 1, _id: 0 } }
// $group - Group by field and aggregate
{ $group: { _id: '$status', count: { $sum: 1 }, avgAge: { $avg: '$age' } } }
// $sort - Sort documents
{ $sort: { createdAt: -1 } }
// $limit - Limit number of documents
{ $limit: 10 }
// $skip - Skip documents
{ $skip: 20 }
// $lookup - Join with other collections
{
$lookup: {
from: 'posts',
localField: '_id',
foreignField: 'userId',
as: 'userPosts'
}
}
// $unwind - Flatten array field
{ $unwind: '$tags' }Example: Complex Aggregation
const stats = await users.aggregate([
// Find active users over 18
{ $match: { status: 'active', age: { $gte: 18 } } },
// Group by country and get stats
{
$group: {
_id: '$country',
count: { $sum: 1 },
avgAge: { $avg: '$age' },
emails: { $push: '$email' }
}
},
// Sort by count descending
{ $sort: { count: -1 } },
// Get top 5
{ $limit: 5 },
// Rename _id field
{ $project: { country: '$_id', count: 1, avgAge: 1, _id: 0 } }
]).toArray();Indexing
Indexes speed up queries significantly.
const users = db.collection('users');
// Create single field index
await users.createIndex({ email: 1 });
// Create unique index (no duplicates)
await users.createIndex({ email: 1 }, { unique: true });
// Create compound index (multiple fields)
await users.createIndex({ country: 1, city: 1 });
// Create text index for full-text search
await users.createIndex({ name: 'text', description: 'text' });
// Create TTL index (auto-delete after time)
await sessions.createIndex({ createdAt: 1 }, { expireAfterSeconds: 3600 });
// List indexes
const indexes = await users.listIndexes().toArray();
console.log(indexes);
// Drop index
await users.dropIndex('email_1');Transactions (🟡 Intermediate)
Multi-document transactions ensure consistency.
const session = client.startSession();
try {
await session.withTransaction(async () => {
const usersCol = db.collection('users');
const accountsCol = db.collection('accounts');
// Transfer money between accounts
await usersCol.updateOne(
{ _id: userId1 },
{ $inc: { balance: -100 } },
{ session }
);
await usersCol.updateOne(
{ _id: userId2 },
{ $inc: { balance: 100 } },
{ session }
);
// Log transaction
await accountsCol.insertOne(
{ from: userId1, to: userId2, amount: 100 },
{ session }
);
});
} finally {
await session.endSession();
}Data Modeling Best Practices
Embedding vs References
// EMBEDDING - nest related data (good for small, related data)
{
_id: ObjectId(),
name: 'Alice',
address: {
street: '123 Main St',
city: 'NYC',
zip: '10001'
}
}
// REFERENCE - link to other documents (good for large, shared data)
{
_id: ObjectId(),
name: 'Alice',
addressId: ObjectId('...')
}Schema Validation
await db.createCollection('users', {
validator: {
$jsonSchema: {
bsonType: 'object',
required: ['name', 'email'],
properties: {
name: { bsonType: 'string' },
email: { bsonType: 'string' },
age: { bsonType: 'int', minimum: 0, maximum: 120 },
tags: { bsonType: 'array', items: { bsonType: 'string' } }
}
}
}
});Mongoose (ODM for MongoDB) (🟡 Intermediate)
Object Document Mapper makes MongoDB easier.
const mongoose = require('mongoose');
// Connect
await mongoose.connect('mongodb://localhost:27017/myDatabase');
// Define schema
const userSchema = new mongoose.Schema({
name: { type: String, required: true },
email: { type: String, unique: true },
age: Number,
createdAt: { type: Date, default: Date.now }
});
// Create model
const User = mongoose.model('User', userSchema);
// Create document
const user = await User.create({
name: 'Alice',
email: 'alice@example.com',
age: 25
});
// Find documents
const users = await User.find({ age: { $gte: 18 } });
// Update
await User.updateOne({ _id: user._id }, { age: 26 });
// Delete
await User.deleteOne({ _id: user._id });Best Practices
- Use indexes on frequently queried fields - Speeds up reads significantly
- Validate data with schema validation - Ensure data integrity
- Use transactions for multi-document updates - Maintain consistency
- Embed small, related data - Query efficiency
- Reference large, shared data - Avoid duplication
- Use projection to limit fields - Reduce data transfer
- Monitor slow queries - Use explain() to analyze query performance
- Use connection pooling - Better performance with multiple queries
Summary
MongoDB is flexible, scalable, and developer-friendly:
- Document-oriented - store JSON-like documents
- Flexible schema - change structure anytime
- Powerful queries - find, filter, aggregate data
- Indexes - fast queries on large datasets
- Transactions - ensure consistency across documents
- Scalable - replicate and shard data across servers
Perfect for modern web applications, APIs, and real-time data!