MongoDB Mastery Guide
Complete guide from beginner to advanced
The Complete MongoDB Mastery Guide
A comprehensive journey through MongoDB fundamentals to advanced database administration and optimization.
Understanding MongoDB: The Leading NoSQL Database
MongoDB is a document-oriented NoSQL database that provides high performance, high availability, and easy scalability. Unlike traditional relational databases, MongoDB uses JSON-like documents with optional schemas, making data integration faster and more flexible.
MongoDB was first developed by MongoDB Inc. in 2007 and has since become one of the most popular NoSQL databases, used by companies like Adobe, Google, eBay, and Forbes for handling diverse and rapidly changing data requirements.
Did you know? The name "MongoDB" comes from the word "humongous," reflecting its ability to handle large amounts of data. MongoDB's document model maps naturally to objects in application code, making it intuitive for developers.
1. MongoDB Basics & Fundamentals
Getting Started with MongoDB
// Connect to MongoDB
mongosh "mongodb://localhost:27017"
// Show databases
show dbs
// Use a database
use company
// Show collections
show collections
// Basic operations with the company database
db.createCollection("employees")
// Insert a document
db.employees.insertOne({
name: "John Doe",
email: "john.doe@company.com",
salary: 50000,
department: "Engineering",
hireDate: new Date("2020-01-15"),
skills: ["JavaScript", "Node.js", "MongoDB"]
})
// Find documents
db.employees.find()
// Get database statistics
db.stats()
// Get collection statistics
db.employees.stats()
// Working with BSON data types
db.dataTypesDemo.insertOne({
string: "Hello MongoDB",
number: 42,
decimal: 99.99,
boolean: true,
array: ["item1", "item2", "item3"],
object: { key: "value", nested: { deep: "data" } },
date: new Date(),
null: null,
regex: /pattern/i,
binary: BinData(0, "binary data"),
objectId: ObjectId(),
timestamp: Timestamp(),
undefined: undefined
})MongoDB Document Structure
// Document structure examples
// Simple user document
{
_id: ObjectId("507f1f77bcf86cd799439011"),
username: "johndoe",
email: "john@example.com",
profile: {
firstName: "John",
lastName: "Doe",
age: 30,
address: {
street: "123 Main St",
city: "New York",
state: "NY",
zipCode: "10001"
}
},
preferences: {
theme: "dark",
notifications: true,
language: "en"
},
tags: ["developer", "premium", "active"],
createdAt: ISODate("2023-01-15T10:30:00Z"),
updatedAt: ISODate("2023-06-20T14:45:00Z")
}
// E-commerce product document
{
_id: ObjectId("64a1b2c3d4e5f67890123456"),
sku: "LAPTOP-001",
name: "Gaming Laptop",
description: "High-performance gaming laptop",
category: "Electronics",
price: 999.99,
cost: 650.00,
specifications: {
processor: "Intel i7",
ram: "16GB",
storage: "512GB SSD",
graphics: "RTX 3060"
},
inventory: {
quantity: 50,
reserved: 5,
available: 45
},
variants: [
{
color: "Black",
price: 999.99,
images: ["black1.jpg", "black2.jpg"]
},
{
color: "White",
price: 1029.99,
images: ["white1.jpg", "white2.jpg"]
}
],
reviews: [
{
userId: ObjectId("64b2c3d4e5f678901234567"),
rating: 5,
comment: "Excellent performance!",
createdAt: new Date("2023-06-15")
},
{
userId: ObjectId("64c3d4e5f6789012345678"),
rating: 4,
comment: "Good value for money",
createdAt: new Date("2023-06-18")
}
],
tags: ["gaming", "laptop", "electronics", "premium"],
isActive: true,
createdAt: new Date(),
updatedAt: new Date()
}
// Blog post with comments
{
_id: ObjectId("64d5e6f7a8b9c0d1e2f34567"),
title: "Introduction to MongoDB",
content: "MongoDB is a document-oriented NoSQL database...",
author: {
userId: ObjectId("64e6f7a8b9c0d1e2f345678"),
name: "Jane Smith",
avatar: "avatar.jpg"
},
categories: ["Database", "NoSQL", "Tutorial"],
tags: ["mongodb", "nosql", "beginner"],
metadata: {
views: 1500,
likes: 45,
shares: 12,
readingTime: 5
},
comments: [
{
_id: ObjectId("64f7a8b9c0d1e2f3456789"),
user: "user123",
text: "Great article!",
createdAt: new Date("2023-07-10"),
likes: 3,
replies: [
{
user: "author",
text: "Thank you!",
createdAt: new Date("2023-07-11")
}
]
}
],
status: "published",
publishedAt: new Date("2023-07-01"),
createdAt: new Date(),
updatedAt: new Date()
}MongoDB Shell Basics
// Basic shell operations
// Switch to database
use mydb
// Create collection explicitly
db.createCollection("users")
// Insert single document
db.users.insertOne({
name: "Alice Johnson",
email: "alice@example.com",
age: 28,
city: "Boston"
})
// Insert multiple documents
db.users.insertMany([
{
name: "Bob Smith",
email: "bob@example.com",
age: 32,
city: "New York"
},
{
name: "Carol Davis",
email: "carol@example.com",
age: 25,
city: "Chicago"
},
{
name: "David Wilson",
email: "david@example.com",
age: 35,
city: "San Francisco"
}
])
// Find all documents
db.users.find()
// Pretty print results
db.users.find().pretty()
// Count documents
db.users.countDocuments()
// Find with condition
db.users.find({ city: "New York" })
// Find with projection (select fields)
db.users.find(
{ city: "New York" },
{ name: 1, email: 1, _id: 0 }
)
// Sort results
db.users.find().sort({ age: -1 }) // Descending
db.users.find().sort({ name: 1 }) // Ascending
// Limit results
db.users.find().limit(5)
// Skip documents
db.users.find().skip(10).limit(5)
// Combination
db.users.find()
.sort({ age: -1 })
.limit(10)
.skip(20)
// Distinct values
db.users.distinct("city")
// Collection information
db.users.stats()
db.users.getIndexes()
db.users.totalSize()2. CRUD Operations
Create Operations
// Create operations examples
// Insert single document
db.products.insertOne({
name: "Wireless Mouse",
category: "Electronics",
price: 29.99,
brand: "TechBrand",
specifications: {
connectivity: "Bluetooth",
battery: "Rechargeable",
dpi: 1600
},
tags: ["wireless", "mouse", "electronics"],
inStock: true,
createdAt: new Date()
})
// Insert multiple documents
db.products.insertMany([
{
name: "Mechanical Keyboard",
category: "Electronics",
price: 79.99,
brand: "KeyMaster",
specifications: {
type: "Mechanical",
switches: "Blue",
backlight: "RGB"
},
tags: ["keyboard", "mechanical", "gaming"],
inStock: true,
createdAt: new Date()
},
{
name: "Gaming Monitor",
category: "Electronics",
price: 299.99,
brand: "ViewPlus",
specifications: {
size: "27 inch",
resolution: "1440p",
refreshRate: 144
},
tags: ["monitor", "gaming", "display"],
inStock: false,
createdAt: new Date()
}
])
// Insert with write concern
db.products.insertOne(
{
name: "Webcam",
price: 49.99,
category: "Electronics"
},
{
writeConcern: { w: "majority", wtimeout: 5000 }
}
)
// Insert with validation (if schema validation exists)
db.products.insertOne({
name: "Laptop Stand",
price: 39.99,
category: "Accessories"
})
// Bulk write operations
db.products.bulkWrite([
{
insertOne: {
document: {
name: "USB Cable",
price: 12.99,
category: "Accessories"
}
}
},
{
insertOne: {
document: {
name: "Laptop Bag",
price: 45.99,
category: "Accessories"
}
}
}
])
// Insert with array of embedded documents
db.orders.insertOne({
orderNumber: "ORD-001",
customer: {
name: "John Doe",
email: "john@example.com"
},
items: [
{
productId: ObjectId("64a1b2c3d4e5f67890123456"),
productName: "Wireless Mouse",
quantity: 2,
price: 29.99
},
{
productId: ObjectId("64b2c3d4e5f678901234567"),
productName: "USB Cable",
quantity: 1,
price: 12.99
}
],
totalAmount: 72.97,
status: "pending",
createdAt: new Date()
})Read Operations
// Read operations examples
// Basic find operations
db.users.find() // All documents
db.users.findOne() // Single document
// Query operators
db.users.find({ age: { $eq: 25 } }) // Equal to
db.users.find({ age: { $ne: 25 } }) // Not equal to
db.users.find({ age: { $gt: 25 } }) // Greater than
db.users.find({ age: { $gte: 25 } }) // Greater than or equal
db.users.find({ age: { $lt: 40 } }) // Less than
db.users.find({ age: { $lte: 40 } }) // Less than or equal
// Multiple conditions
db.users.find({ age: { $gte: 25, $lte: 35 } }) // Between
db.users.find({ city: { $in: ["New York", "Boston"] } }) // In array
db.users.find({ city: { $nin: ["Chicago", "Miami"] } }) // Not in array
// Logical operators
db.users.find({ $and: [
{ age: { $gte: 25 } },
{ city: "New York" }
]})
db.users.find({ $or: [
{ city: "New York" },
{ city: "Boston" }
]})
db.users.find({ $nor: [
{ age: { $lt: 25 } },
{ city: "Chicago" }
]})
db.users.find({ age: { $not: { $lt: 25 } } }) // Not less than 25
// Element operators
db.users.find({ age: { $exists: true } }) // Field exists
db.users.find({ phone: { $exists: false } }) // Field doesn't exist
db.users.find({ age: { $type: "number" } }) // Field type
// Array operators
db.products.find({ tags: "wireless" }) // Array contains
db.products.find({ tags: { $all: ["wireless", "electronics"] } }) // All elements
db.products.find({ tags: { $size: 3 } }) // Array size
db.products.find({ "tags.0": "wireless" }) // Positional element
// Evaluation operators
db.users.find({ name: { $regex: /^J/ } }) // Regex
db.users.find({ name: { $regex: "John", $options: "i" } }) // Case insensitive
db.users.find({ $expr: { $gt: ["$age", "$minAge"] } }) // Expression
// Projection (field selection)
db.users.find({}, { name: 1, email: 1 }) // Include only name and email
db.users.find({}, { password: 0, ssn: 0 }) // Exclude fields
db.users.find({}, { name: 1, "address.city": 1 }) // Include nested fields
// Sorting
db.users.find().sort({ age: 1 }) // Ascending
db.users.find().sort({ age: -1 }) // Descending
db.users.find().sort({ city: 1, age: -1 }) // Multiple fields
// Pagination
db.users.find().skip(20).limit(10) // Page 3 with 10 items per page
// Count
db.users.countDocuments({ city: "New York" })
db.users.estimatedDocumentCount()
// Distinct values
db.users.distinct("city")
db.users.distinct("department.name")Update Operations
// Update operations examples
// Update single document
db.users.updateOne(
{ _id: ObjectId("507f1f77bcf86cd799439011") },
{ $set: { city: "Los Angeles" } }
)
// Update multiple documents
db.users.updateMany(
{ city: "New York" },
{ $set: { region: "Northeast" } }
)
// Replace entire document
db.users.replaceOne(
{ _id: ObjectId("507f1f77bcf86cd799439011") },
{
name: "John Doe Updated",
email: "john.updated@example.com",
city: "San Francisco",
updatedAt: new Date()
}
)
// Update operators
db.products.updateOne(
{ _id: ObjectId("64a1b2c3d4e5f67890123456") },
{
$set: { price: 899.99 }, // Set field
$unset: { oldPrice: "" }, // Remove field
$inc: { quantity: -1 }, // Increment/decrement
$mul: { price: 0.9 }, // Multiply
$rename: { "specs": "specifications" }, // Rename field
$min: { lowestPrice: 850 }, // Set if lower
$max: { highestPrice: 950 }, // Set if higher
$currentDate: { updatedAt: true } // Set current date
}
)
// Array update operators
db.products.updateOne(
{ _id: ObjectId("64a1b2c3d4e5f67890123456") },
{
$push: { tags: "new" }, // Add to array
$pull: { tags: "old" }, // Remove from array
$addToSet: { tags: "unique" }, // Add if not exists
$pop: { tags: 1 }, // Remove first (1) or last (-1)
$pullAll: { tags: ["obsolete", "deprecated"] } // Remove multiple
}
)
// Array positional updates
db.orders.updateOne(
{ "items.productName": "Wireless Mouse" },
{ $set: { "items.$.price": 24.99 } } // $ for matched array element
)
// Update with aggregation pipeline (MongoDB 4.2+)
db.users.updateOne(
{ _id: ObjectId("507f1f77bcf86cd799439011") },
[
{
$set: {
fullName: { $concat: ["$firstName", " ", "$lastName"] },
ageGroup: {
$switch: {
branches: [
{ case: { $lt: ["$age", 25] }, then: "Young" },
{ case: { $lt: ["$age", 40] }, then: "Adult" },
{ case: { $gte: ["$age", 40] }, then: "Senior" }
],
default: "Unknown"
}
},
lastUpdated: "$$NOW"
}
}
]
)
// Upsert (update or insert if not exists)
db.users.updateOne(
{ email: "newuser@example.com" },
{
$setOnInsert: {
name: "New User",
createdAt: new Date()
},
$set: {
lastLogin: new Date()
}
},
{ upsert: true }
)
// Bulk updates
db.products.bulkWrite([
{
updateOne: {
filter: { category: "Electronics" },
update: { $set: { taxExempt: false } }
}
},
{
updateMany: {
filter: { price: { $lt: 50 } },
update: { $inc: { price: 5 } }
}
}
])
// Find and modify (atomic operation)
db.products.findOneAndUpdate(
{ _id: ObjectId("64a1b2c3d4e5f67890123456"), quantity: { $gt: 0 } },
{ $inc: { quantity: -1 } },
{ returnDocument: "after" } // Return updated document
)Delete Operations
// Delete operations examples
// Delete single document
db.users.deleteOne({ _id: ObjectId("507f1f77bcf86cd799439011") })
// Delete multiple documents
db.users.deleteMany({ status: "inactive" })
// Delete all documents in collection (be careful!)
// db.users.deleteMany({})
// Delete with conditions
db.products.deleteMany({
price: { $lt: 10 },
category: "Electronics"
})
// Find and delete (atomic operation)
db.orders.findOneAndDelete(
{ status: "cancelled" },
{ sort: { createdAt: 1 } } // Delete oldest cancelled order
)
// Delete with write concern
db.users.deleteOne(
{ _id: ObjectId("507f1f77bcf86cd799439011") },
{ writeConcern: { w: "majority", wtimeout: 5000 } }
)
// Bulk delete operations
db.products.bulkWrite([
{
deleteOne: {
filter: { sku: "OBSOLETE-001" }
}
},
{
deleteMany: {
filter: {
category: "Old Category",
lastSold: { $lt: new Date("2020-01-01") }
}
}
}
])
// Safe delete patterns
// 1. Archive before delete
const docToDelete = db.users.findOne({ _id: ObjectId("507f1f77bcf86cd799439011") })
db.deletedUsers.insertOne({
...docToDelete,
deletedAt: new Date(),
deletedBy: "admin"
})
db.users.deleteOne({ _id: ObjectId("507f1f77bcf86cd799439011") })
// 2. Soft delete (update instead of delete)
db.users.updateOne(
{ _id: ObjectId("507f1f77bcf86cd799439011") },
{
$set: {
isDeleted: true,
deletedAt: new Date(),
deletedBy: "admin"
}
}
)
// 3. Batch delete with backup
const batchSize = 1000
let deletedCount = 0
do {
const result = db.users.deleteMany(
{
status: "inactive",
lastLogin: { $lt: new Date("2022-01-01") }
}
).limit(batchSize)
deletedCount = result.deletedCount
print(`Deleted {deletedCount{'}'} documents`)
// Optional: sleep to reduce load
sleep(100)
} while (deletedCount === batchSize)
// Drop entire collection
// db.users.drop()
// Drop database
// db.dropDatabase()3. Aggregation Framework
Basic Aggregation Pipeline
// Basic aggregation examples
// Sample orders collection
db.orders.insertMany([
{
orderId: "ORD-001",
customer: "John Doe",
amount: 150.00,
status: "completed",
items: [
{ product: "Laptop", quantity: 1, price: 1000 },
{ product: "Mouse", quantity: 2, price: 25 }
],
date: new Date("2023-01-15")
},
{
orderId: "ORD-002",
customer: "Jane Smith",
amount: 75.50,
status: "completed",
items: [
{ product: "Keyboard", quantity: 1, price: 75.50 }
],
date: new Date("2023-01-16")
},
{
orderId: "ORD-003",
customer: "John Doe",
amount: 200.00,
status: "pending",
items: [
{ product: "Monitor", quantity: 1, price: 200 }
],
date: new Date("2023-01-17")
}
])
// Simple aggregation - group by customer
db.orders.aggregate([
{
$group: {
_id: "$customer",
totalOrders: { $sum: 1 },
totalAmount: { $sum: "$amount" },
averageOrder: { $avg: "$amount" }
}
}
])
// Multiple stages
db.orders.aggregate([
// Stage 1: Filter documents
{
$match: {
status: "completed",
date: { $gte: new Date("2023-01-01") }
}
},
// Stage 2: Group by customer
{
$group: {
_id: "$customer",
totalSpent: { $sum: "$amount" },
orderCount: { $sum: 1 }
}
},
// Stage 3: Sort by total spent
{
$sort: { totalSpent: -1 }
},
// Stage 4: Project final output
{
$project: {
customer: "$_id",
totalSpent: 1,
orderCount: 1,
averageOrder: { $divide: ["$totalSpent", "$orderCount"] },
_id: 0
}
}
])
// Unwind arrays and work with array elements
db.orders.aggregate([
{ $match: { status: "completed" } },
{ $unwind: "$items" }, // Deconstruct items array
{
$group: {
_id: "$items.product",
totalQuantity: { $sum: "$items.quantity" },
totalRevenue: { $sum: { $multiply: ["$items.quantity", "$items.price"] } },
timesOrdered: { $sum: 1 }
}
},
{ $sort: { totalRevenue: -1 } }
])
// Lookup - join with another collection
db.orders.aggregate([
{
$lookup: {
from: "customers", // Collection to join
localField: "customer", // Field from orders
foreignField: "name", // Field from customers
as: "customerInfo" // Output array field
}
},
{
$unwind: "$customerInfo" // Convert array to object
},
{
$project: {
orderId: 1,
amount: 1,
customerName: "$customerInfo.name",
customerEmail: "$customerInfo.email",
customerTier: "$customerInfo.tier"
}
}
])
// Faceted search - multiple aggregations in one query
db.products.aggregate([
{
$facet: {
// Price ranges
priceRanges: [
{
$bucket: {
groupBy: "$price",
boundaries: [0, 50, 100, 200, 500],
default: "500+",
output: {
count: { $sum: 1 },
avgPrice: { $avg: "$price" }
}
}
}
],
// Categories
categories: [
{
$group: {
_id: "$category",
count: { $sum: 1 }
}
}
],
// Brands
brands: [
{
$group: {
_id: "$brand",
count: { $sum: 1 },
avgPrice: { $avg: "$price" }
}
}
]
}
}
])Advanced Aggregation Operations
// Advanced aggregation examples
// Window functions (MongoDB 5.0+)
db.sales.aggregate([
{
$setWindowFields: {
partitionBy: "$region",
sortBy: { date: 1 },
output: {
runningTotal: {
$sum: "$amount",
window: {
documents: ["unbounded", "current"]
}
},
movingAvg: {
$avg: "$amount",
window: {
documents: [-2, 0] // Current and previous 2
}
},
rankInRegion: {
$denseRank: {}
}
}
}
}
])
// Graph lookup for hierarchical data
db.categories.aggregate([
{
$graphLookup: {
from: "categories",
startWith: "$_id",
connectFromField: "_id",
connectToField: "parentId",
as: "ancestors",
maxDepth: 3,
depthField: "level"
}
}
])
// Time series aggregation (MongoDB 5.0+)
db.measurements.aggregate([
{
$match: {
timestamp: {
$gte: new Date("2023-01-01"),
$lt: new Date("2023-02-01")
}
}
},
{
$setWindowFields: {
partitionBy: "$sensorId",
sortBy: { timestamp: 1 },
output: {
hourlyAvg: {
$avg: "$value",
window: {
range: [-3600, 0], // 1 hour in seconds
unit: "second"
}
}
}
}
}
])
// Complex data transformation
db.employees.aggregate([
// Filter active employees
{ $match: { status: "active" } },
// Add computed fields
{
$addFields: {
tenure: {
$divide: [
{ $subtract: [new Date(), "$hireDate"] },
1000 * 60 * 60 * 24 * 365 // Convert to years
]
},
fullName: { $concat: ["$firstName", " ", "$lastName"] }
}
},
// Lookup department information
{
$lookup: {
from: "departments",
localField: "departmentId",
foreignField: "_id",
as: "department"
}
},
// Unwind department array
{ $unwind: { path: "$department", preserveNullAndEmptyArrays: true } },
// Group by department with multiple metrics
{
$group: {
_id: "$department.name",
employeeCount: { $sum: 1 },
avgSalary: { $avg: "$salary" },
maxSalary: { $max: "$salary" },
minSalary: { $min: "$salary" },
totalBudget: { $sum: "$salary" },
avgTenure: { $avg: "$tenure" },
employees: {
$push: {
name: "$fullName",
salary: "$salary",
tenure: "$tenure"
}
}
}
},
// Add performance metrics
{
$addFields: {
salaryRange: { $subtract: ["$maxSalary", "$minSalary"] },
budgetPerEmployee: { $divide: ["$totalBudget", "$employeeCount"] }
}
},
// Final projection
{
$project: {
department: "$_id",
employeeCount: 1,
avgSalary: { $round: ["$avgSalary", 2] },
salaryRange: { $round: ["$salaryRange", 2] },
totalBudget: { $round: ["$totalBudget", 2] },
avgTenure: { $round: ["$avgTenure", 2] },
budgetPerEmployee: { $round: ["$budgetPerEmployee", 2] },
highEarners: {
$filter: {
input: "$employees",
as: "emp",
cond: { $gt: ["$$emp.salary", "$avgSalary"] }
}
},
_id: 0
}
},
// Sort by total budget
{ $sort: { totalBudget: -1 } }
])
// Conditional aggregation with $switch
db.orders.aggregate([
{
$project: {
orderId: 1,
amount: 1,
status: 1,
priority: {
$switch: {
branches: [
{
case: { $gte: ["$amount", 1000] },
then: "High"
},
{
case: { $gte: ["$amount", 500] },
then: "Medium"
},
{
case: { $gte: ["$amount", 100] },
then: "Low"
}
],
default: "Standard"
}
},
sizeCategory: {
$cond: {
if: { $gte: ["$amount", 500] },
then: "Large",
else: "Small"
}
}
}
}
])
// Array aggregation operators
db.products.aggregate([
{
$project: {
name: 1,
prices: "$variants.price",
minPrice: { $min: "$variants.price" },
maxPrice: { $max: "$variants.price" },
avgPrice: { $avg: "$variants.price" },
priceRange: { $subtract: [{ $max: "$variants.price" }, { $min: "$variants.price" }] },
variantCount: { $size: "$variants" },
firstVariant: { $arrayElemAt: ["$variants", 0] },
lastVariant: { $arrayElemAt: ["$variants", -1] }
}
}
])
// Merge aggregation results into collection (MongoDB 4.2+)
db.orders.aggregate([
{ $match: { date: { $gte: new Date("2023-01-01") } } },
{
$group: {
_id: { $dateToString: { format: "%Y-%m", date: "$date" } },
totalSales: { $sum: "$amount" },
orderCount: { $sum: 1 }
}
},
{
$merge: {
into: "monthly_sales",
on: "_id",
whenMatched: "replace",
whenNotMatched: "insert"
}
}
])4. Indexes & Performance
Index Types and Creation
// Index creation and management
// Single field index
db.users.createIndex({ email: 1 }) // Ascending
db.users.createIndex({ createdAt: -1 }) // Descending
// Compound index
db.orders.createIndex({ customerId: 1, createdAt: -1 })
// Multikey index (for arrays)
db.products.createIndex({ tags: 1 })
// Text index for text search
db.articles.createIndex(
{ title: "text", content: "text" },
{
weights: { title: 10, content: 5 }, // Title more important
default_language: "english"
}
)
// 2dsphere index for geospatial queries
db.places.createIndex({ location: "2dsphere" })
// Hashed index for sharding
db.users.createIndex({ _id: "hashed" })
// Unique index
db.users.createIndex({ email: 1 }, { unique: true })
// Partial index (only index documents that match filter)
db.orders.createIndex(
{ status: 1 },
{
partialFilterExpression: {
status: { $in: ["pending", "processing"] }
}
}
)
// TTL index (automatically expire documents)
db.sessions.createIndex(
{ lastAccess: 1 },
{ expireAfterSeconds: 3600 } // 1 hour
)
// Sparse index (only index documents that have the field)
db.users.createIndex(
{ phone: 1 },
{ sparse: true }
)
// Case insensitive index
db.users.createIndex(
{ email: 1 },
{
collation: {
locale: "en",
strength: 2 // Case insensitive
}
}
)
// Wildcard index (MongoDB 4.2+)
db.products.createIndex({ "metadata.$**": 1 })
// View indexes
db.users.getIndexes()
// Index statistics
db.users.aggregate([{ $indexStats: {} }])
// Drop index
db.users.dropIndex("email_1")
// Drop all indexes (except _id)
// db.users.dropIndexes()
// Reindex collection
// db.users.reIndex()Query Performance and Optimization
// Query performance analysis
// Explain query execution
db.users.find({ email: "john@example.com" }).explain("executionStats")
// Explain with different verbosity levels
db.users.find({ age: { $gt: 25 } }).explain("queryPlanner")
db.users.find({ age: { $gt: 25 } }).explain("executionStats")
db.users.find({ age: { $gt: 25 } }).explain("allPlansExecution")
// Analyze slow queries using database profiler
// Enable profiler
db.setProfilingLevel(1, 50) // Level 1, slowms = 50
// Or level 2 for all operations
// db.setProfilingLevel(2)
// View profiler data
db.system.profile.find().sort({ ts: -1 }).limit(10)
// Disable profiler
// db.setProfilingLevel(0)
// Performance optimization techniques
// 1. Use covered queries (query can be satisfied entirely by index)
db.users.createIndex({ email: 1, name: 1 })
db.users.find(
{ email: "john@example.com" },
{ _id: 0, email: 1, name: 1 } // Projection matches index
)
// 2. Use efficient query patterns
// Good: Uses index
db.users.find({ email: "john@example.com" })
// Bad: Cannot use index efficiently
db.users.find({ $or: [
{ email: /^john/ },
{ name: /john/ }
]})
// 3. Use projection to limit returned fields
db.users.find({}, { name: 1, email: 1 }) // Only return needed fields
// 4. Use hint to force index usage
db.users.find({ email: "john@example.com" }).hint({ email: 1 })
// 5. Avoid large skip values
// Instead of:
db.users.find().skip(10000).limit(10)
// Use range-based pagination:
const lastId = ObjectId("507f1f77bcf86cd799439011")
db.users.find({ _id: { $gt: lastId } }).limit(10)
// 6. Use bulk operations for multiple writes
const bulk = db.users.initializeUnorderedBulkOp()
bulk.find({ status: "inactive" }).update({ $set: { lastNotified: new Date() } })
bulk.execute()
// 7. Monitor and optimize memory usage
// Check working set size
db.serverStatus().mem
// Check index size
db.users.totalIndexSize()
// 8. Use appropriate write concern
db.users.insertOne(
{ name: "John" },
{ writeConcern: { w: 1 } } // Faster, less durable
)
db.users.insertOne(
{ name: "John" },
{ writeConcern: { w: "majority" } } // Slower, more durable
)
// Common performance issues and solutions
// Issue: Collection scans
// Solution: Create appropriate indexes
db.users.createIndex({ queryField: 1 })
// Issue: Large sort operations
// Solution: Use indexed sort fields
db.users.createIndex({ sortField: 1 })
db.users.find().sort({ sortField: 1 })
// Issue: Inefficient array queries
// Solution: Use multikey indexes and $elemMatch
db.products.createIndex({ "reviews.rating": 1 })
db.products.find({ "reviews.rating": { $gte: 4 } })
// Issue: Growing documents causing moves
// Solution: Pre-allocate space or use padding
db.createCollection("preallocated", {
storageEngine: { wiredTiger: { configString: "allocation_size=4KB" } }
})
// Performance monitoring commands
// Current operations
db.currentOp()
// Database stats
db.stats()
// Collection stats
db.users.stats()
// Server status
db.serverStatus()
// Replica set status (if applicable)
rs.status()5. Data Modeling
Document Design Patterns
// Data modeling patterns and examples
// Pattern 1: Embedded Documents (One-to-Few)
// Use when: Related data is frequently accessed together
db.users.insertOne({
_id: "user123",
name: "John Doe",
address: {
street: "123 Main St",
city: "New York",
state: "NY",
zip: "10001"
},
contacts: [
{ type: "home", phone: "555-0101" },
{ type: "mobile", phone: "555-0102" }
]
})
// Pattern 2: Document References (One-to-Many)
// Use when: Related data grows without bound
db.authors.insertOne({
_id: "author1",
name: "Jane Smith",
bio: "Professional writer"
})
db.books.insertMany([
{
title: "Book 1",
authorId: "author1",
published: new Date("2020-01-01")
},
{
title: "Book 2",
authorId: "author1",
published: new Date("2021-01-01")
}
])
// Pattern 3: Extended Reference (Hybrid)
// Use when: Need some related data frequently
db.orders.insertOne({
_id: "order123",
customer: {
id: "cust456",
name: "John Doe", // Frequently accessed field
email: "john@example.com"
},
items: [
{
productId: "prod789",
productName: "Laptop", // Frequently accessed field
price: 999.99,
quantity: 1
}
],
// Full customer data in customers collection
// Full product data in products collection
})
// Pattern 4: Bucket Pattern (for time series/IoT)
// Use when: High volume of time-series data
db.sensorReadings.insertOne({
sensorId: "sensor1",
start: new Date("2023-01-01"),
end: new Date("2023-01-01T01:00:00"),
readings: [
{ timestamp: new Date("2023-01-01T00:00:00"), value: 23.4 },
{ timestamp: new Date("2023-01-01T00:01:00"), value: 23.5 },
// ... 58 more readings for 1 hour bucket
],
stats: {
min: 23.4,
max: 24.1,
avg: 23.7
}
})
// Pattern 5: Computed Pattern
// Use when: Expensive computations are frequently needed
db.products.insertOne({
_id: "prod123",
name: "Gaming Laptop",
reviews: [
{ rating: 5, comment: "Great!" },
{ rating: 4, comment: "Good" },
{ rating: 5, comment: "Excellent" }
],
// Pre-computed values
reviewStats: {
averageRating: 4.67,
totalReviews: 3,
ratingDistribution: { 5: 2, 4: 1, 3: 0, 2: 0, 1: 0 }
}
})
// Pattern 6: Subset Pattern
// Use when: Large arrays but only need subset frequently
db.products.insertOne({
_id: "prod456",
name: "Popular Product",
// Full reviews in separate collection
// But keep recent reviews embedded for quick access
recentReviews: [
{ rating: 5, comment: "Love it!", date: new Date() },
{ rating: 4, comment: "Good product", date: new Date() }
],
totalReviews: 150 // Counter for all reviews
})
// Pattern 7: Polymorphic Pattern
// Use when: Different document types in same collection
db.content.insertMany([
{
_id: "content1",
type: "article",
title: "MongoDB Guide",
content: "Long article content...",
author: "John Doe",
published: new Date()
},
{
_id: "content2",
type: "video",
title: "MongoDB Tutorial",
videoUrl: "https://example.com/video",
duration: 3600,
author: "Jane Smith",
published: new Date()
}
])
// Schema validation (MongoDB 3.6+)
db.createCollection("users", {
validator: {
$jsonSchema: {
bsonType: "object",
required: ["name", "email", "createdAt"],
properties: {
name: {
bsonType: "string",
description: "must be a string and is required"
},
email: {
bsonType: "string",
pattern: "^.+@.+\..+$",
description: "must be a valid email and is required"
},
age: {
bsonType: "int",
minimum: 0,
maximum: 150,
description: "must be an integer between 0 and 150"
},
createdAt: {
bsonType: "date",
description: "must be a date and is required"
}
}
}
},
validationLevel: "strict",
validationAction: "error"
})
// Add validation to existing collection
db.runCommand({
collMod: "users",
validator: {
$jsonSchema: {
// schema definition
}
}
})Relationship Modeling
// Relationship modeling examples
// One-to-One Relationship
// Option 1: Embedded (preferred for one-to-one)
db.users.insertOne({
_id: "user1",
name: "John Doe",
profile: {
bio: "Software developer",
website: "https://johndoe.com",
avatar: "avatar.jpg"
}
})
// Option 2: Referenced (if profile is very large or rarely accessed)
db.users.insertOne({
_id: "user1",
name: "John Doe",
profileId: "profile1"
})
db.profiles.insertOne({
_id: "profile1",
userId: "user1",
bio: "Software developer",
website: "https://johndoe.com",
avatar: "avatar.jpg"
})
// One-to-Many Relationship
// Option 1: Embedded (few related documents, frequently accessed together)
db.authors.insertOne({
_id: "author1",
name: "Jane Smith",
books: [
{ title: "Book 1", published: new Date("2020-01-01") },
{ title: "Book 2", published: new Date("2021-01-01") }
]
})
// Option 2: Referenced (many related documents, parent rarely accessed with children)
db.authors.insertOne({
_id: "author1",
name: "Jane Smith"
})
db.books.insertMany([
{ title: "Book 1", authorId: "author1", published: new Date("2020-01-01") },
{ title: "Book 2", authorId: "author1", published: new Date("2021-01-01") }
])
// Many-to-Many Relationship
// Option 1: Array of references (if bounded)
db.students.insertOne({
_id: "student1",
name: "Alice",
courses: ["course1", "course2"]
})
db.courses.insertOne({
_id: "course1",
name: "Mathematics",
students: ["student1", "student2"]
})
// Option 2: Separate collection for relationships (if unbounded)
db.student_courses.insertMany([
{ studentId: "student1", courseId: "course1", enrolled: new Date() },
{ studentId: "student1", courseId: "course2", enrolled: new Date() },
{ studentId: "student2", courseId: "course1", enrolled: new Date() }
])
// Tree Structures
// Option 1: Parent References (for simple trees)
db.categories.insertMany([
{ _id: "root", name: "Root", parent: null },
{ _id: "electronics", name: "Electronics", parent: "root" },
{ _id: "computers", name: "Computers", parent: "electronics" },
{ _id: "laptops", name: "Laptops", parent: "computers" }
])
// Option 2: Child References (for frequently accessed children)
db.categories.insertOne({
_id: "electronics",
name: "Electronics",
parent: "root",
children: ["computers", "phones", "tablets"]
})
// Option 3: Materialized Paths (for complex hierarchies)
db.categories.insertOne({
_id: "laptops",
name: "Laptops",
path: "root.electronics.computers.laptops"
})
// Option 4: Nested Sets (for frequent subtree queries)
db.categories.insertOne({
_id: "electronics",
name: "Electronics",
left: 2,
right: 9
})
// Graph Relationships
// Option 1: Adjacency List
db.users.insertOne({
_id: "user1",
name: "Alice",
friends: ["user2", "user3"]
})
// Option 2: Edge Collection (for rich relationships)
db.friendships.insertMany([
{ user1: "user1", user2: "user2", since: new Date(), closeness: 0.8 },
{ user1: "user1", user2: "user3", since: new Date(), closeness: 0.6 }
])
// Querying relationships
// One-to-Many with $lookup
db.orders.aggregate([
{
$lookup: {
from: "customers",
localField: "customerId",
foreignField: "_id",
as: "customer"
}
},
{ $unwind: "$customer" }
])
// Many-to-Many with multiple $lookup
db.students.aggregate([
{
$lookup: {
from: "student_courses",
localField: "_id",
foreignField: "studentId",
as: "enrollments"
}
},
{
$lookup: {
from: "courses",
localField: "enrollments.courseId",
foreignField: "_id",
as: "courses"
}
}
])
// Tree traversal with $graphLookup
db.categories.aggregate([
{
$match: { _id: "laptops" }
},
{
$graphLookup: {
from: "categories",
startWith: "$parent",
connectFromField: "parent",
connectToField: "_id",
as: "ancestors",
depthField: "level"
}
}
])
// Data modeling best practices
// 1. Favor embedding for:
// - Related data accessed together
// - One-to-few relationships
// - Data that doesn't change frequently
// 2. Favor referencing for:
// - Many related documents
// - Large documents that would make parent too big
// - Data that changes independently
// 3. Consider write/read patterns:
// - Embed for mostly reads, reference for frequent writes
// - Consider data consistency requirements
// 4. Plan for growth:
// - Avoid unbounded arrays
// - Use appropriate patterns for scalability
// 5. Use appropriate indexes:
// - Index fields used in queries and sorts
// - Consider compound indexes for common query patterns6. Transactions & ACID Properties
Multi-Document Transactions
// MongoDB transactions examples
// Basic transaction pattern
const session = db.getMongo().startSession()
try {
session.startTransaction({
readConcern: { level: "snapshot" },
writeConcern: { w: "majority" },
readPreference: "primary"
})
// Operations within transaction
const account1 = db.accounts.findOne(
{ _id: "account1" },
{ session }
)
const account2 = db.accounts.findOne(
{ _id: "account2" },
{ session }
)
// Update operations
db.accounts.updateOne(
{ _id: "account1" },
{ $inc: { balance: -100 } },
{ session }
)
db.accounts.updateOne(
{ _id: "account2" },
{ $inc: { balance: 100 } },
{ session }
)
// Insert operation
db.transactions.insertOne(
{
from: "account1",
to: "account2",
amount: 100,
date: new Date()
},
{ session }
)
// Commit transaction
session.commitTransaction()
console.log("Transaction committed successfully")
} catch (error) {
// Abort transaction on error
session.abortTransaction()
console.log("Transaction aborted:", error)
} finally {
session.endSession()
}
// Transaction with retry logic
async function performTransfer(fromAccount, toAccount, amount) {
let retryCount = 0
const maxRetries = 3
while (retryCount < maxRetries) {
const session = db.getMongo().startSession()
try {
session.startTransaction()
// Check sufficient balance
const sourceAccount = await db.accounts.findOne(
{ _id: fromAccount, balance: { $gte: amount } },
{ session }
)
if (!sourceAccount) {
throw new Error("Insufficient balance")
}
// Perform transfer
await db.accounts.updateOne(
{ _id: fromAccount },
{ $inc: { balance: -amount } },
{ session }
)
await db.accounts.updateOne(
{ _id: toAccount },
{ $inc: { balance: amount } },
{ session }
)
await db.transactions.insertOne(
{
from: fromAccount,
to: toAccount,
amount: amount,
status: "completed",
timestamp: new Date()
},
{ session }
)
await session.commitTransaction()
console.log("Transfer completed successfully")
return
} catch (error) {
await session.abortTransaction()
if (error.hasErrorLabel("TransientTransactionError") &&
retryCount < maxRetries - 1) {
retryCount++
console.log(`Retrying transaction (attempt {retryCount + 1{'}'})`)
await new Promise(resolve => setTimeout(resolve, 100 * retryCount))
continue
}
console.log("Transfer failed:", error)
throw error
} finally {
session.endSession()
}
}
}
// Multi-collection transaction
const session = db.getMongo().startSession()
try {
session.startTransaction()
// Update inventory
db.products.updateOne(
{ _id: "product1", "inventory.quantity": { $gte: 2 } },
{
$inc: { "inventory.quantity": -2 },
$push: {
"inventory.reservations": {
orderId: "order123",
quantity: 2,
reservedAt: new Date()
}
}
},
{ session }
)
// Create order
db.orders.insertOne(
{
_id: "order123",
customerId: "customer1",
items: [
{
productId: "product1",
quantity: 2,
price: 29.99
}
],
total: 59.98,
status: "confirmed",
createdAt: new Date()
},
{ session }
)
// Update customer's order history
db.customers.updateOne(
{ _id: "customer1" },
{
$push: {
orders: {
orderId: "order123",
date: new Date(),
amount: 59.98
}
},
$inc: { totalSpent: 59.98 }
},
{ session }
)
session.commitTransaction()
} catch (error) {
session.abortTransaction()
throw error
} finally {
session.endSession()
}
// Read preferences and concerns in transactions
// Read from primary with strong consistency
const session = db.getMongo().startSession({
causalConsistency: false // Strong consistency
})
session.startTransaction({
readConcern: { level: "majority" }, // Read confirmed writes
writeConcern: { w: "majority", j: true }, // Journal acknowledged
readPreference: "primary" // Read from primary only
})
// Optimistic concurrency control with transactions
async function updateWithOptimisticLock(documentId, updateFn) {
let retries = 0
const maxRetries = 5
while (retries < maxRetries) {
const session = db.getMongo().startSession()
try {
session.startTransaction()
// Read current document with version
const doc = await db.documents.findOne(
{ _id: documentId },
{ session }
)
if (!doc) throw new Error("Document not found")
// Apply business logic (might modify doc)
const updatedDoc = updateFn(doc)
updatedDoc.version = doc.version + 1
// Update with version check
const result = await db.documents.updateOne(
{
_id: documentId,
version: doc.version // Ensure no concurrent modification
},
{ $set: updatedDoc },
{ session }
)
if (result.modifiedCount === 0) {
throw new Error("Concurrent modification detected")
}
await session.commitTransaction()
return updatedDoc
} catch (error) {
await session.abortTransaction()
if (error.message === "Concurrent modification detected" &&
retries < maxRetries - 1) {
retries++
continue
}
throw error
} finally {
session.endSession()
}
}
}Consistency Models and Write Concerns
// Write concerns and consistency models
// Write concern examples
db.products.insertOne(
{ name: "Product", price: 100 },
{ writeConcern: { w: 1 } } // Acknowledged by primary only
)
db.products.insertOne(
{ name: "Product", price: 100 },
{ writeConcern: { w: "majority" } } // Acknowledged by majority
)
db.products.insertOne(
{ name: "Product", price: 100 },
{ writeConcern: { w: 3 } } // Acknowledged by 3 nodes
)
db.products.insertOne(
{ name: "Product", price: 100 },
{ writeConcern: { w: "majority", j: true } } // Journal acknowledged
)
db.products.insertOne(
{ name: "Product", price: 100 },
{ writeConcern: { w: "majority", wtimeout: 5000 } } // 5 second timeout
)
// Read concern examples
// Local (default) - may return unacknowledged writes
db.products.find().readConcern("local")
// Majority - only returns majority-acknowledged writes
db.products.find().readConcern("majority")
// Linearizable - strongest consistency
db.products.find().readConcern("linearizable")
// Snapshot - consistent snapshot across multiple documents
db.products.find().readConcern("snapshot")
// Read preference examples
// Primary (default) - read from primary only
db.products.find().readPref("primary")
// PrimaryPreferred - primary, fallback to secondary
db.products.find().readPref("primaryPreferred")
// Secondary - read from secondary only
db.products.find().readPref("secondary")
// SecondaryPreferred - secondary, fallback to primary
db.products.find().readPref("secondaryPreferred")
// Nearest - lowest latency node
db.products.find().readPref("nearest")
// Causal consistency
const session = db.getMongo().startSession({ causalConsistency: true })
// Operation 1: Write with causal consistency
db.products.insertOne(
{ name: "Product A" },
{ session }
)
// Operation 2: Read will see the write (causally consistent)
db.products.find(
{ name: "Product A" },
{ session }
)
// Operation 3: Another causally consistent operation
db.products.updateOne(
{ name: "Product A" },
{ $set: { price: 100 } },
{ session }
)
session.endSession()
// Retryable writes (enabled by default)
db.products.insertOne(
{ name: "Retryable Product" },
{
writeConcern: { w: "majority" },
retryWrites: true // Automatically retry on transient errors
}
)
// Change streams for real-time data
const changeStream = db.products.watch([
{ $match: { "operationType": { $in: ["insert", "update", "delete"] } } }
])
changeStream.on("change", (change) => {
console.log("Change detected:", change)
switch (change.operationType) {
case "insert":
console.log("New document:", change.fullDocument)
break
case "update":
console.log("Updated fields:", change.updateDescription.updatedFields)
break
case "delete":
console.log("Deleted document ID:", change.documentKey._id)
break
}
})
// Resume change stream from specific point
const resumeToken = changeStream.resumeToken
const resumedStream = db.products.watch([], { resumeAfter: resumeToken })
// Aggregation with read concern and preference
db.orders.aggregate([
{ $match: { status: "completed" } },
{
$group: {
_id: "$customerId",
totalSpent: { $sum: "$amount" }
}
}
], {
readConcern: { level: "majority" },
readPreference: "secondaryPreferred",
maxTimeMS: 30000 // 30 second timeout
})
// Bulk write with mixed concerns
db.products.bulkWrite([
{
insertOne: {
document: { name: "Product B", price: 200 }
}
},
{
updateOne: {
filter: { name: "Product A" },
update: { $set: { price: 150 } }
}
},
{
deleteOne: {
filter: { name: "Old Product" }
}
}
], {
writeConcern: { w: "majority", wtimeout: 5000 },
ordered: false // Continue on errors
})
// Best practices for consistency
// 1. Use appropriate write concern:
// - w:1 for performance, w:"majority" for durability
// - Include j:true for crash safety
// - Set reasonable wtimeout
// 2. Choose read concern based on needs:
// - "local" for performance
// - "majority" for consistency
// - "linearizable" for strongest guarantees
// 3. Use read preference wisely:
// - "primary" for strong consistency
// - "secondary" for read scaling
// - "nearest" for low latency
// 4. Use transactions for multi-document atomicity
// 5. Implement retry logic for transient errors
// 6. Monitor replication lag in replica sets7. Database Administration
User Management and Security
// User management and security
// Create admin user (first user has root privileges)
db.createUser({
user: "admin",
pwd: "securepassword123",
roles: ["root"]
})
// Create application user with specific privileges
db.createUser({
user: "appuser",
pwd: "apppassword123",
roles: [
{
role: "readWrite",
db: "myapp"
},
{
role: "read",
db: "reporting"
}
]
})
// Create read-only user
db.createUser({
user: "reportuser",
pwd: "reportpassword123",
roles: ["read"]
})
// Built-in roles
// Database User Roles: read, readWrite
// Database Administration Roles: dbAdmin, dbOwner, userAdmin
// Cluster Administration Roles: clusterAdmin, clusterManager, clusterMonitor, hostManager
// Backup and Restoration Roles: backup, restore
// All-Database Roles: readAnyDatabase, readWriteAnyDatabase, userAdminAnyDatabase, dbAdminAnyDatabase
// Superuser Roles: root, __system
// Create custom role
db.createRole({
role: "dataManager",
privileges: [
{
resource: { db: "myapp", collection: "products" },
actions: ["find", "insert", "update", "remove"]
},
{
resource: { db: "myapp", collection: "orders" },
actions: ["find", "insert"]
}
],
roles: []
})
// Grant role to user
db.grantRolesToUser("appuser", ["dataManager"])
// Revoke role from user
db.revokeRolesFromUser("appuser", ["dataManager"])
// View users and roles
db.getUsers()
db.getRoles({ showBuiltinRoles: true })
// Update user password
db.changeUserPassword("appuser", "newpassword123")
// Drop user
db.dropUser("olduser")
// Authentication and connection
// Connect with authentication
mongosh "mongodb://appuser:apppassword123@localhost:27017/myapp"
// Connect with connection string options
mongosh "mongodb://appuser:apppassword123@host1:27017,host2:27017/myapp?replicaSet=myReplicaSet&authSource=admin"
// Enable authentication in mongod configuration
// security:
// authorization: enabled
// Encryption at rest (Enterprise Feature)
// Enable in configuration:
// security:
// enableEncryption: true
// encryptionKeyFile: /path/to/keyfile
// SSL/TLS configuration
// net:
// ssl:
// mode: requireSSL
// PEMKeyFile: /path/to/mongodb.pem
// CAFile: /path/to/ca.pem
// Auditing (Enterprise Feature)
// auditLog:
// destination: file
// format: JSON
// path: /var/log/mongodb/audit.json
// View current operations
db.currentOp()
// Kill operation
db.killOp(opid)
// Database commands for administration
// Get server status
db.serverStatus()
// Get database stats
db.stats()
// Get collection stats
db.products.stats()
// Compact collection (reclaims space)
db.products.compact()
// Validate collection (checks data integrity)
db.products.validate({ full: true })
// Repair database (use with caution)
// db.repairDatabase()
// Set profiling level
db.setProfilingLevel(1, 100) // Profile slow operations > 100ms
// View profiler data
db.system.profile.find().sort({ ts: -1 })
// Backup and restore commands
// mongodump for backup
// mongodump --uri="mongodb://localhost:27017/myapp" --out=/backup
// mongorestore for restore
// mongorestore --uri="mongodb://localhost:27017/myapp" /backup/myapp
// mongoexport for JSON/CSV export
// mongoexport --uri="mongodb://localhost:27017/myapp" --collection=products --out=products.json
// mongoimport for import
// mongoimport --uri="mongodb://localhost:27017/myapp" --collection=products --file=products.jsonBackup, Restore, and Monitoring
// Backup and monitoring strategies
// Backup script example (using mongodump)
function performBackup() {
const date = new Date().toISOString().split('T')[0]
const backupPath = `/backup/mongodb-{date{'}'}`
// Perform backup
const result = runProgram('mongodump', [
'--uri', 'mongodb://localhost:27017/myapp',
'--out', backupPath,
'--gzip' // Compress backup
])
if (result === 0) {
print(`Backup completed successfully: {backupPath{'}'}`)
// Log backup completion
db.backupLog.insertOne({
type: "scheduled",
path: backupPath,
status: "completed",
size: getFolderSize(backupPath),
timestamp: new Date()
})
} else {
print("Backup failed")
db.backupLog.insertOne({
type: "scheduled",
path: backupPath,
status: "failed",
timestamp: new Date()
})
}
}
// Point-in-time backup with oplog (for replica sets)
function performPITBackup() {
const session = db.getMongo().startSession()
const backupTime = new Date()
try {
session.startTransaction()
// Flush writes to disk
db.fsyncLock()
// Perform filesystem backup here
// (copy database files while locked)
db.fsyncUnlock()
// Record backup information
db.backupInfo.insertOne({
timestamp: backupTime,
type: "point-in-time",
oplog: db.getSiblingDB("local").oplog.rs.find().sort({ $natural: -1 }).limit(1).next(),
status: "completed"
})
session.commitTransaction()
} catch (error) {
session.abortTransaction()
throw error
} finally {
session.endSession()
}
}
// Monitoring setup
// Create monitoring collection
db.metrics.insertOne({
type: "server_status",
data: db.serverStatus(),
timestamp: new Date()
})
// Custom monitoring function
function collectMetrics() {
const metrics = {}
// Server status
metrics.serverStatus = db.serverStatus()
// Database stats
metrics.dbStats = db.stats()
// Collection stats for important collections
metrics.collections = {}
const importantCollections = ["users", "products", "orders"]
importantCollections.forEach(coll => {
metrics.collections[coll] = db[coll].stats()
})
// Current operations
metrics.currentOp = db.currentOp().inprog.slice(0, 10) // Top 10
// Replication status (if replica set)
try {
metrics.replStatus = rs.status()
} catch (e) {
metrics.replStatus = { error: "Not a replica set" }
}
// Save metrics
db.monitoring.insertOne({
timestamp: new Date(),
metrics: metrics
})
// Clean up old metrics (keep 30 days)
const thirtyDaysAgo = new Date(Date.now() - 30 * 24 * 60 * 60 * 1000)
db.monitoring.deleteMany({ timestamp: { $lt: thirtyDaysAgo } })
}
// Performance monitoring queries
// Slow queries analysis
db.system.profile.aggregate([
{
$match: {
op: { $ne: "command" }, // Filter out commands
millis: { $gt: 100 } // Queries taking > 100ms
}
},
{
$group: {
_id: {
ns: "$ns", // namespace (collection)
op: "$op" // operation type
},
count: { $sum: 1 },
avgDuration: { $avg: "$millis" },
maxDuration: { $max: "$millis" },
totalDuration: { $sum: "$millis" }
}
},
{
$sort: { totalDuration: -1 }
}
])
// Index usage statistics
db.products.aggregate([{ $indexStats: {} }])
// Connection monitoring
db.serverStatus().connections
// Memory usage
const mem = db.serverStatus().mem
print(`Resident Memory: {(mem.resident / 1024).toFixed(2){'}'} MB`)
print(`Virtual Memory: {(mem.virtual / 1024).toFixed(2){'}'} MB`)
// Cache hit ratio
const wt = db.serverStatus().wiredTiger
const cache = wt["cache"]
const hitRatio = (cache["bytes read into cache"] + cache["bytes written from cache"]) /
(cache["bytes read into cache"] + cache["bytes read from cache"] + 1)
print(`Cache hit ratio: {(hitRatio * 100).toFixed(2){'}'}%`)
// Alerting system setup
function checkAlerts() {
const alerts = []
// Check connection count
const connections = db.serverStatus().connections
if (connections.current > connections.available * 0.8) {
alerts.push("High connection count: " + connections.current)
}
// Check replication lag
try {
const status = rs.status()
status.members.forEach(member => {
if (member.optime && member.optime.ts) {
const lag = status.members[0].optime.ts - member.optime.ts
if (lag > 100) { // 100 operations behind
alerts.push(`Replication lag for {member.name{'}'}: {lag{'}'} ops`)
}
}
})
} catch (e) {
// Not a replica set
}
// Check disk space (would need system command integration)
// Check slow operations
const slowOps = db.system.profile.count({
millis: { $gt: 1000 },
ts: { $gt: new Date(Date.now() - 5 * 60 * 1000) } // Last 5 minutes
})
if (slowOps > 10) {
alerts.push(`High number of slow operations: {slowOps{'}'}`)
}
// Save alerts
if (alerts.length > 0) {
db.alerts.insertMany(alerts.map(alert => ({
message: alert,
severity: "warning",
timestamp: new Date()
})))
}
return alerts
}
// Automated maintenance tasks
// Create maintenance job collection
db.maintenanceJobs.insertOne({
name: "daily_cleanup",
description: "Clean up old data and update statistics",
schedule: "0 2 * * *", // 2 AM daily
lastRun: new Date(),
nextRun: new Date(Date.now() + 24 * 60 * 60 * 1000),
enabled: true
})
// Maintenance function
function runMaintenance() {
const now = new Date()
// Clean up old sessions (30 days)
const thirtyDaysAgo = new Date(now - 30 * 24 * 60 * 60 * 1000)
db.sessions.deleteMany({ lastAccess: { $lt: thirtyDaysAgo } })
// Archive old orders (1 year)
const oneYearAgo = new Date(now - 365 * 24 * 60 * 60 * 1000)
const oldOrders = db.orders.find({
createdAt: { $lt: oneYearAgo },
status: "completed"
}).toArray()
if (oldOrders.length > 0) {
db.ordersArchive.insertMany(oldOrders)
db.orders.deleteMany({ _id: { $in: oldOrders.map(o => o._id) } })
}
// Update statistics
db.command({ collStats: "products" })
db.command({ collStats: "users" })
db.command({ collStats: "orders" })
// Update maintenance log
db.maintenanceLog.insertOne({
job: "daily_cleanup",
started: now,
completed: new Date(),
details: {
sessionsRemoved: db.sessions.countDocuments({ lastAccess: { $lt: thirtyDaysAgo } }),
ordersArchived: oldOrders.length
}
})
}8. MongoDB Atlas & Cloud
Atlas Features and Management
// MongoDB Atlas features and integration
// Connecting to Atlas cluster
// Connection string format:
mongosh "mongodb+srv://username:password@cluster0.mongodb.net/databaseName?retryWrites=true&w=majority"
// Atlas specific connection options
const connectionString = "mongodb+srv://user:pass@cluster.mongodb.net/mydb" +
"?retryWrites=true" +
"&w=majority" +
"&readPreference=secondaryPreferred" +
"&maxPoolSize=50" +
"&socketTimeoutMS=30000"
// Atlas CLI commands (requires Atlas CLI installation)
// atlas clusters list
// atlas clusters create MyCluster --provider AWS --region US_EAST_1 --tier M10
// atlas clusters pause MyCluster
// atlas clusters resume MyCluster
// Database Users management in Atlas
// Create database user via Atlas API
const newUser = {
databaseName: "admin",
username: "appuser",
password: "securepassword123",
roles: [
{
databaseName: "myapp",
roleName: "readWrite"
}
]
}
// Network access configuration
const ipAccessList = {
ipAddress: "203.0.113.1",
comment: "Office IP"
}
// Backup and restore in Atlas
// Enable cloud backup
// Backups are automatic in Atlas
// Restore from backup via UI or API
const restoreRequest = {
snapshotId: "snapshot123",
targetClusterName: "restored-cluster",
targetGroupId: "project123"
}
// Atlas Search configuration
// Create search index
db.runCommand({
createSearchIndex: {
name: "products_search",
definition: {
mappings: {
dynamic: true,
fields: {
name: {
type: "string",
analyzer: "lucene.standard"
},
description: {
type: "string",
analyzer: "lucene.standard"
},
price: {
type: "number"
}
}
}
}
}
})
// Use Atlas Search
db.products.aggregate([
{
$search: {
index: "products_search",
text: {
query: "wireless bluetooth speaker",
path: ["name", "description"]
}
}
},
{
$project: {
name: 1,
description: 1,
score: { $meta: "searchScore" }
}
}
])
// Atlas Data Lake integration
// Query data across Atlas and S3
db.runCommand({
aggregate: 1,
pipeline: [
{
$unionWith: {
coll: "atlas_cluster.products",
pipeline: [
{ $match: { category: "Electronics" } }
]
}
},
{
$unionWith: {
coll: "data_lake.s3_products",
pipeline: [
{ $match: { price: { $gt: 100 } } }
]
}
}
],
cursor: { batchSize: 100 }
})
// Realm integration (serverless functions)
// Realm function example
exports = function(payload) {
const collection = context.services.get("mongodb-atlas").db("myapp").collection("orders")
return collection.insertOne({
...payload,
createdAt: new Date(),
status: "pending"
})
}
// Charts for data visualization
// Embedded chart configuration
const chartConfig = {
dataSource: {
type: "atlas",
clusterName: "Cluster0",
dbName: "myapp",
collectionName: "orders"
},
query: {
status: "completed"
},
chartType: "bar",
xAxis: "$product",
yAxis: "$quantity"
}
// Performance Advisor in Atlas
// Get performance recommendations
const recommendations = db.getSiblingDB("admin").aggregate([
{
$currentOp: {}
},
{
$match: {
active: true,
secs_running: { $gt: 10 }
}
}
])
// Monitoring and alerts in Atlas
// Set up alert configuration
const alertConfig = {
eventTypeName: "OUTSIDE_METRIC_THRESHOLD",
enabled: true,
notifications: [
{
typeName: "EMAIL",
intervalMin: 60,
delayMin: 0
}
],
metricThreshold: {
metricName: "ASSERT_REGULAR",
operator: "GREATER_THAN",
threshold: 10,
units: "RAW",
mode: "AVERAGE"
}
}
// Best practices for Atlas
// 1. Use appropriate cluster tier for workload
// 2. Enable auto-scaling for variable workloads
// 3. Use VPC peering for security
// 4. Configure proper backup retention
// 5. Set up monitoring and alerts
// 6. Use Atlas Search for full-text search
// 7. Consider Data Lake for archival data
// 8. Use Realm for serverless functions
// Cost optimization strategies
// 1. Right-size cluster tiers
// 2. Use auto-pause for development clusters
// 3. Archive old data to cheaper storage
// 4. Use proper indexing to reduce compute
// 5. Monitor and optimize query patterns
// Security best practices in Atlas
// 1. Enable network isolation with VPC
// 2. Use database encryption at rest and in transit
// 3. Implement proper IAM roles and policies
// 4. Regular security audits and updates
// 5. Use Atlas auditing for complianceMigration and Integration
// Migration strategies and integration patterns
// Live migration with mongomirror
// mongomirror --source mongodb://source-server:27017 --destination mongodb+srv://atlas-cluster
// mongodump and mongorestore migration
// Step 1: Dump from source
// mongodump --uri="mongodb://source:27017/mydb" --out=./dump
// Step 2: Restore to Atlas
// mongorestore --uri="mongodb+srv://user:pass@cluster.mongodb.net/mydb" ./dump/mydb
// MongoDB Atlas Live Migration Service
// Uses change streams for zero-downtime migration
// Application integration patterns
// Node.js application connection
const { MongoClient } = require('mongodb')
const uri = "mongodb+srv://username:password@cluster.mongodb.net/mydb?retryWrites=true&w=majority"
const client = new MongoClient(uri, {
useNewUrlParser: true,
useUnifiedTopology: true,
poolSize: 10,
serverSelectionTimeoutMS: 5000,
socketTimeoutMS: 45000
})
async function connect() {
try {
await client.connect()
console.log("Connected to MongoDB Atlas")
return client.db("mydb")
} catch (error) {
console.error("Connection failed:", error)
process.exit(1)
}
}
// Python application connection
from pymongo import MongoClient
from pymongo.server_api import ServerApi
uri = "mongodb+srv://username:password@cluster.mongodb.net/?retryWrites=true&w=majority"
client = MongoClient(uri, server_api=ServerApi('1'))
db = client.mydb
# Verify connection
try:
client.admin.command('ping')
print("Connected to MongoDB Atlas")
except Exception as e:
print("Connection failed:", e)
// Change streams for real-time integration
const changeStream = db.collection('orders').watch()
changeStream.on('change', (change) => {
// Integrate with other services
switch (change.operationType) {
case 'insert':
// Send to analytics service
sendToAnalytics(change.fullDocument)
break
case 'update':
// Update cache
updateCache(change.documentKey, change.updateDescription)
break
case 'delete':
// Remove from cache
removeFromCache(change.documentKey)
break
}
})
// Integration with AWS services
// S3 integration for backup/archive
const { S3Client, PutObjectCommand } = require("@aws-sdk/client-s3")
async function backupToS3(collectionName) {
const data = await db.collection(collectionName).find().toArray()
const s3Client = new S3Client({ region: "us-east-1" })
const command = new PutObjectCommand({
Bucket: "my-backup-bucket",
Key: `backups/{collectionName{'}'}-{Date.now(){'}'}.json`,
Body: JSON.stringify(data)
})
await s3Client.send(command)
}
// Lambda function integration
exports.handler = async (event) => {
const client = await connect()
const db = client.db("mydb")
try {
const result = await db.collection("orders").insertOne(event)
return {
statusCode: 200,
body: JSON.stringify({ insertedId: result.insertedId })
}
} catch (error) {
return {
statusCode: 500,
body: JSON.stringify({ error: error.message })
}
}
}
// Integration with Azure
// Cosmos DB API for MongoDB migration
// Use same connection string format
const cosmosUri = "mongodb://accountname:password@accountname.mongo.cosmos.azure.com:10255/?ssl=true"
// Integration with Google Cloud
// Cloud Functions integration
const { MongoClient } = require('mongodb')
exports.mongoFunction = async (req, res) => {
const client = new MongoClient(process.env.MONGODB_URI)
try {
await client.connect()
const db = client.db("mydb")
const result = await db.collection("visits").insertOne({
timestamp: new Date(),
userAgent: req.get('User-Agent')
})
res.status(200).send(`Visit recorded: {result.insertedId{'}'}`)
} finally {
await client.close()
}
}
// Data pipeline integration
// Kafka integration
const { Kafka } = require('kafkajs')
const kafka = new Kafka({
clientId: 'mongo-producer',
brokers: ['kafka1:9092', 'kafka2:9092']
})
const producer = kafka.producer()
// Send MongoDB changes to Kafka
changeStream.on('change', async (change) => {
await producer.send({
topic: 'mongo-changes',
messages: [
{ value: JSON.stringify(change) }
]
})
})
// ETL pipeline with MongoDB
async function runETL() {
// Extract
const sourceData = await db.collection('raw_data').find().toArray()
// Transform
const transformedData = sourceData.map(item => ({
...item,
processed: true,
processedAt: new Date(),
derivedField: calculateDerivedField(item)
}))
// Load
if (transformedData.length > 0) {
await db.collection('processed_data').insertMany(transformedData)
}
}
// Monitoring and observability integration
// Integration with Datadog
const dogstatsd = require('node-dogstatsd').StatsD
const statsd = new dogstatsd()
// Send MongoDB metrics to Datadog
setInterval(() => {
const status = db.serverStatus()
statsd.gauge('mongodb.connections.current', status.connections.current)
statsd.gauge('mongodb.memory.resident', status.mem.resident)
}, 30000)
// Integration with Prometheus
const client = require('prom-client')
const mongoQueryDuration = new client.Histogram({
name: 'mongodb_query_duration_seconds',
help: 'Duration of MongoDB queries',
labelNames: ['collection', 'operation']
})
// Wrap MongoDB operations
async function timedFind(collection, query) {
const end = mongoQueryDuration.startTimer({ collection, operation: 'find' })
try {
return await collection.find(query).toArray()
} finally {
end()
}
}
// Disaster recovery strategies
// Multi-region deployment in Atlas
const multiRegionConfig = {
name: "global-cluster",
replicationSpecs: [
{
numShards: 1,
regionsConfig: {
"US_EAST_1": {
analyticsNodes: 0,
electableNodes: 3,
priority: 7,
readOnlyNodes: 0
},
"EU_WEST_1": {
analyticsNodes: 0,
electableNodes: 2,
priority: 3,
readOnlyNodes: 0
}
}
}
]
}
// Backup and recovery procedures
async function disasterRecovery() {
// 1. Identify latest backup
const latestBackup = await db.backupInfo.find().sort({ timestamp: -1 }).limit(1).next()
// 2. Restore from backup
// This would use Atlas UI/API or mongorestore
// 3. Verify data integrity
const verification = await db.command({ dbStats: 1 })
// 4. Update application configuration
// Point to new cluster
return {
status: "recovered",
backupUsed: latestBackup.timestamp,
verification: verification
}
}💻 Hands-On Practice Exercises
Beginner Level
- 1Create a database for a blog with posts, comments, and users
- 2Practice basic CRUD operations with embedded and referenced documents
- 3Design a product catalog with categories and variants
- 4Implement simple aggregation queries for analytics
- 5Create indexes for common query patterns
Intermediate Level
- 1Design and implement an e-commerce database with orders, products, and customers
- 2Create complex aggregation pipelines for business intelligence
- 3Implement multi-document transactions for order processing
- 4Set up change streams for real-time notifications
- 5Optimize queries using proper indexing and projection
Advanced Level
- 1Design a multi-tenant SaaS application with data partitioning
- 2Implement time-series data patterns for IoT applications
- 3Set up MongoDB Atlas cluster with proper security and backup
- 4Create data migration strategies from relational databases
- 5Design and implement graph relationships for social networks
🛠️ Essential MongoDB Tools
MongoDB Compass
GUI for MongoDB with schema analysis, performance insights, and query building
- Visual Query Builder
- Performance Analytics
- Schema Explorer
- Index Management
Primary GUI tool for database exploration, query building, and performance optimization
MongoDB Shell (mongosh)
Advanced MongoDB shell with modern features and improved usability
- Syntax Highlighting
- Auto-completion
- Modern JavaScript
- Plugin Support
Command-line interface for database administration and development
MongoDB Atlas
Fully managed cloud database service with automated operations
- Automated Scaling
- Backup & Recovery
- Monitoring & Alerts
- Global Clusters
Cloud deployment and management platform for production applications
MongoDB Database Tools
Command-line utilities for data management and migration
- mongodump/mongorestore
- mongoexport/mongoimport
- mongostat
- mongotop
Data backup, restoration, import/export, and monitoring utilities
🎯 MongoDB Career Paths
MongoDB Developer
Document Design, Aggregation, Application Integration
Database Administrator
Performance Tuning, Backup/Recovery, Security, Scaling
Data Architect
Data Modeling, Schema Design, Enterprise Architecture
Continue Your MongoDB Journey!
You've now explored the comprehensive landscape of MongoDB database management, from basic document operations to advanced administration and cloud deployment. MongoDB continues to be the leading NoSQL database for modern applications.
Continue exploring advanced topics like sharding, advanced aggregation patterns, machine learning integration, and stay updated with the latest MongoDB features in the rapidly evolving database landscape.