MongoDB is a popular NoSQL document database that stores data in flexible, JSON-like documents. It's designed for scalability and performance, making it ideal for modern applications.
// MongoDB Document
{
"_id": ObjectId("..."),
"name": "John Doe",
"email": "john@example.com",
"address": {
"street": "123 Main St",
"city": "New York"
},
"hobbies": ["reading", "gaming"]
}
// SQL Tables
-- users table
-- addresses table
-- hobbies table
-- user_hobbies junction table
// Architecture Hierarchy
Database: "myapp"
└── Collection: "users"
└── Document: { "_id": ObjectId("..."), "name": "John" }
└── Field: "name" = "John"
// Multiple collections in one database
use myapp
db.users.find()
db.products.find()
db.orders.find()
BSON (Binary JSON) is the binary format used by MongoDB to store documents. It extends JSON with additional data types.
// BSON Data Types
{
"_id": ObjectId("507f1f77bcf86cd799439011"),
"string": "Hello World",
"number": 42,
"boolean": true,
"date": new Date("2023-01-01"),
"array": [1, 2, 3],
"object": { "key": "value" },
"null": null,
"regex": /pattern/i,
"binary": BinData(0, "base64data"),
"timestamp": Timestamp(1234567890, 1)
}
# Ubuntu/Debian
sudo apt-get install mongodb
# macOS with Homebrew
brew tap mongodb/brew
brew install mongodb-community
# Windows
# Download MSI installer from mongodb.com
# Start MongoDB
sudo systemctl start mongod
sudo systemctl enable mongod
# Check status
sudo systemctl status mongod
# Connect to MongoDB
mongosh
# Connect to MongoDB
mongosh
mongosh "mongodb://localhost:27017"
mongosh "mongodb://username:password@host:port/database"
# Basic shell commands
show dbs # List databases
use mydatabase # Switch database
show collections # List collections
help # Show help
exit # Exit shell
# MongoDB Compass
# Download from mongodb.com/try/download/compass
# Connect using connection string
mongodb://localhost:27017
// Database operations
show dbs // List all databases
use myapp // Switch to database
db // Show current database
db.dropDatabase() // Delete current database
// Collection operations
show collections // List collections
db.createCollection("users") // Create collection
db.users.drop() // Delete collection
db.users.stats() // Collection statistics
// Document structure
{
"_id": ObjectId("..."), // Unique identifier
"field1": "value1", // Field-value pair
"field2": 123,
"nested": { // Nested document
"subfield": "value"
},
"array": [1, 2, 3] // Array field
}
use command to switch/create// Create/switch to database
use myapp
// Database is created when you insert first document
db.users.insertOne({
name: "John Doe",
email: "john@example.com"
})
// List databases (will show myapp now)
show dbs
// Database naming rules
// - Cannot be empty string
// - Cannot contain: /, \, ., " ", $, \0
// - Cannot start with reserved words
// - Case sensitive
// Examples of valid names
use myapp
use my_app
use myApp123
use my-app
// Examples of invalid names
use my app // Contains space
use my.app // Contains dot
use $myapp // Starts with $
createCollection() or insert document// Method 1: Explicit creation
db.createCollection("users")
// Method 2: Implicit creation (insert document)
db.products.insertOne({
name: "Laptop",
price: 999.99
})
// Create collection with options
db.createCollection("logs", {
capped: true,
size: 1000000, // 1MB
max: 1000 // Max 1000 documents
})
// Collection naming rules
// - Cannot be empty string
// - Cannot contain: /, \, ., " ", $, \0
// - Cannot start with reserved words
// - Case sensitive
// Valid collection names
db.users
db.user_profiles
db.userProfiles
db.user-profiles
// Invalid collection names
db.user profiles // Contains space
db.user.profiles // Contains dot
db.user-profiles // Starts with -
// MongoDB Data Types
{
// String
"name": "John Doe",
"email": "john@example.com",
// Numbers
"age": 30, // Integer
"salary": 75000.50, // Double
"decimal": NumberDecimal("123.456"), // Decimal128
// Boolean
"isActive": true,
"verified": false,
// Date
"createdAt": new Date("2023-01-01"),
"updatedAt": new Date(),
// ObjectId
"_id": ObjectId("507f1f77bcf86cd799439011"),
"userId": ObjectId("507f1f77bcf86cd799439012"),
// Array
"hobbies": ["reading", "gaming", "coding"],
"scores": [85, 92, 78, 96],
// Object (Embedded Document)
"address": {
"street": "123 Main St",
"city": "New York",
"zipCode": "10001"
},
// Null
"middleName": null,
// Regular Expression
"pattern": /^[A-Za-z]+$/,
// Binary Data
"binaryData": BinData(0, "base64encodeddata"),
// Timestamp
"timestamp": Timestamp(1234567890, 1)
}
// CREATE
// Insert single document
db.users.insertOne({
name: "John Doe",
email: "john@example.com",
age: 30
})
// Insert multiple documents
db.users.insertMany([
{ name: "Jane Smith", email: "jane@example.com", age: 25 },
{ name: "Bob Johnson", email: "bob@example.com", age: 35 }
])
// READ
// Find all documents
db.users.find()
// Find one document
db.users.findOne({ name: "John Doe" })
// Find with filter
db.users.find({ age: { $gt: 25 } })
// UPDATE
// Update one document
db.users.updateOne(
{ name: "John Doe" },
{ $set: { age: 31 } }
)
// Update multiple documents
db.users.updateMany(
{ age: { $lt: 30 } },
{ $inc: { age: 1 } }
)
// DELETE
// Delete one document
db.users.deleteOne({ name: "John Doe" })
// Delete multiple documents
db.users.deleteMany({ age: { $lt: 25 } })
// Comparison Operators
db.users.find({ age: { $gt: 25 } }) // Greater than
db.users.find({ age: { $gte: 25 } }) // Greater than or equal
db.users.find({ age: { $lt: 30 } }) // Less than
db.users.find({ age: { $lte: 30 } }) // Less than or equal
db.users.find({ age: { $ne: 25 } }) // Not equal
db.users.find({ age: { $in: [25, 30, 35] } }) // In array
db.users.find({ age: { $nin: [25, 30] } }) // Not in array
// Logical Operators
db.users.find({
$and: [
{ age: { $gt: 25 } },
{ email: { $regex: /@gmail\.com$/ } }
]
})
db.users.find({
$or: [
{ age: { $lt: 25 } },
{ age: { $gt: 35 } }
]
})
// Element Operators
db.users.find({ email: { $exists: true } }) // Field exists
db.users.find({ age: { $type: "number" } }) // Field type
// Evaluation Operators
db.users.find({ name: { $regex: /^J/ } }) // Starts with J
db.users.find({ name: { $regex: /n$/ } }) // Ends with n
db.users.find({ name: { $regex: /john/i } }) // Case insensitive
// Complex queries
db.users.find({
$and: [
{ age: { $gte: 18, $lte: 65 } },
{ email: { $exists: true } },
{ $or: [
{ name: { $regex: /^J/ } },
{ name: { $regex: /^B/ } }
]}
]
})
// Include specific fields
db.users.find({}, { name: 1, email: 1 })
// Returns: { "_id": ..., "name": "...", "email": "..." }
// Exclude specific fields
db.users.find({}, { password: 0, secretKey: 0 })
// Returns all fields except password and secretKey
// Include with _id exclusion
db.users.find({}, { name: 1, email: 1, _id: 0 })
// Returns: { "name": "...", "email": "..." }
// Nested field projection
db.users.find({}, { "address.city": 1, "address.zipCode": 1 })
// Array element projection
db.users.find({}, { "hobbies.0": 1, "hobbies.1": 1 })
// Conditional projection
db.users.find({}, {
name: 1,
email: 1,
age: {
$cond: {
if: { $gte: ["$age", 18] },
then: "$age",
else: "$$REMOVE"
}
}
})
// Common projection patterns
// Get only essential user info
db.users.find({}, { name: 1, email: 1, _id: 0 })
// Exclude sensitive data
db.users.find({}, { password: 0, ssn: 0, creditCard: 0 })
// Get user summary
db.users.find({}, {
name: 1,
age: 1,
"address.city": 1,
_id: 0
})
sort() method// Basic sorting
db.users.find().sort({ name: 1 }) // Ascending by name
db.users.find().sort({ age: -1 }) // Descending by age
// Compound sorting
db.users.find().sort({ age: -1, name: 1 })
// Sort by age descending, then name ascending
// Sort with filter
db.users.find({ age: { $gt: 25 } })
.sort({ name: 1 })
// Sort with projection
db.users.find({}, { name: 1, age: 1, _id: 0 })
.sort({ age: -1 })
// Sort by nested fields
db.users.find().sort({ "address.city": 1 })
// Sort by array elements
db.users.find().sort({ "scores.0": -1 })
// Sort with limit (top 10 oldest users)
db.users.find()
.sort({ age: -1 })
.limit(10)
// Sort by date
db.users.find().sort({ createdAt: -1 })
// Sort by multiple criteria
db.users.find().sort({
isActive: -1, // Active users first
age: -1, // Then by age descending
name: 1 // Then by name ascending
})
// Limit results
db.users.find().limit(5) // Get only 5 documents
db.users.find().limit(10) // Get only 10 documents
// Skip documents
db.users.find().skip(5) // Skip first 5 documents
db.users.find().skip(10) // Skip first 10 documents
// Pagination (page 1: documents 1-10)
db.users.find()
.sort({ name: 1 })
.skip(0)
.limit(10)
// Pagination (page 2: documents 11-20)
db.users.find()
.sort({ name: 1 })
.skip(10)
.limit(10)
// Pagination (page 3: documents 21-30)
db.users.find()
.sort({ name: 1 })
.skip(20)
.limit(10)
// Get top 5 users by age
db.users.find()
.sort({ age: -1 })
.limit(5)
// Skip inactive users, get next 10
db.users.find({ isActive: true })
.sort({ createdAt: -1 })
.skip(10)
.limit(10)
// Pagination function
function getUsers(page, pageSize) {
const skip = (page - 1) * pageSize;
return db.users.find()
.sort({ name: 1 })
.skip(skip)
.limit(pageSize);
}
// Usage
getUsers(1, 10); // Page 1, 10 items per page
getUsers(2, 10); // Page 2, 10 items per page
// Basic aggregation
db.users.aggregate([
{ $match: { age: { $gte: 18 } } },
{ $group: { _id: "$city", count: { $sum: 1 } } },
{ $sort: { count: -1 } }
])
// Count users by age group
db.users.aggregate([
{
$group: {
_id: {
$cond: {
if: { $lt: ["$age", 25] },
then: "18-24",
else: {
$cond: {
if: { $lt: ["$age", 35] },
then: "25-34",
else: "35+"
}
}
}
},
count: { $sum: 1 },
avgAge: { $avg: "$age" }
}
},
{ $sort: { _id: 1 } }
])
// Join with orders collection
db.users.aggregate([
{
$lookup: {
from: "orders",
localField: "_id",
foreignField: "userId",
as: "orders"
}
},
{
$project: {
name: 1,
email: 1,
orderCount: { $size: "$orders" },
totalSpent: { $sum: "$orders.amount" }
}
}
])
// Complex aggregation
db.users.aggregate([
{ $match: { isActive: true } },
{
$lookup: {
from: "orders",
localField: "_id",
foreignField: "userId",
as: "orders"
}
},
{
$addFields: {
totalOrders: { $size: "$orders" },
totalSpent: { $sum: "$orders.amount" }
}
},
{
$group: {
_id: "$city",
userCount: { $sum: 1 },
avgOrders: { $avg: "$totalOrders" },
totalRevenue: { $sum: "$totalSpent" }
}
},
{ $sort: { totalRevenue: -1 } }
])
// Create single field index
db.users.createIndex({ email: 1 })
db.users.createIndex({ age: -1 })
// Create compound index
db.users.createIndex({ lastName: 1, firstName: 1 })
db.users.createIndex({ city: 1, age: -1 })
// Create unique index
db.users.createIndex({ email: 1 }, { unique: true })
// Create sparse index (only on documents with field)
db.users.createIndex({ middleName: 1 }, { sparse: true })
// Create text index
db.users.createIndex({ name: "text", bio: "text" })
// Create geospatial index
db.users.createIndex({ location: "2dsphere" })
// List indexes
db.users.getIndexes()
// Drop index
db.users.dropIndex("email_1")
db.users.dropIndex({ email: 1 })
// Drop all indexes (except _id)
db.users.dropIndexes()
// Index options
db.users.createIndex(
{ email: 1 },
{
unique: true,
sparse: true,
background: true,
name: "email_unique_index"
}
)
// Compound index order matters
// Good for queries: { lastName: "Smith", firstName: "John" }
db.users.createIndex({ lastName: 1, firstName: 1 })
// Bad for queries: { firstName: "John" } (without lastName)
// Index won't be used efficiently
// Embedded approach (One-to-Few)
// User with embedded addresses
{
"_id": ObjectId("..."),
"name": "John Doe",
"email": "john@example.com",
"addresses": [
{
"type": "home",
"street": "123 Main St",
"city": "New York",
"zipCode": "10001"
},
{
"type": "work",
"street": "456 Business Ave",
"city": "New York",
"zipCode": "10002"
}
]
}
// Reference approach (One-to-Many)
// User document
{
"_id": ObjectId("..."),
"name": "John Doe",
"email": "john@example.com"
}
// Orders collection
{
"_id": ObjectId("..."),
"userId": ObjectId("..."), // Reference to user
"items": [...],
"total": 150.00,
"date": new Date()
}
// Hybrid approach
// User with some embedded data and references
{
"_id": ObjectId("..."),
"name": "John Doe",
"email": "john@example.com",
"profile": { // Embedded (small, frequently accessed)
"bio": "Software developer",
"avatar": "url",
"preferences": {...}
},
"orderIds": [ // References (large, less frequent)
ObjectId("..."),
ObjectId("...")
]
}
// EMBEDDED DOCUMENTS
// Pros: Atomic operations, single query
// Cons: Document size limit, duplication
// User with embedded profile
{
"_id": ObjectId("..."),
"name": "John Doe",
"profile": {
"bio": "Software developer",
"avatar": "url",
"social": {
"twitter": "@johndoe",
"linkedin": "linkedin.com/in/johndoe"
}
}
}
// Query embedded data
db.users.find({ "profile.social.twitter": "@johndoe" })
// Update embedded data
db.users.updateOne(
{ _id: ObjectId("...") },
{ $set: { "profile.bio": "Updated bio" } }
)
// REFERENCES
// Pros: Normalized data, independent updates
// Cons: Multiple queries, joins needed
// User document
{
"_id": ObjectId("..."),
"name": "John Doe",
"profileId": ObjectId("...")
}
// Profile document
{
"_id": ObjectId("..."),
"bio": "Software developer",
"avatar": "url",
"social": {...}
}
// Query with lookup
db.users.aggregate([
{
$lookup: {
from: "profiles",
localField: "profileId",
foreignField: "_id",
as: "profile"
}
}
])
// WHEN TO USE EACH
// Use Embedded when:
// - Data is small and related
// - Data is frequently accessed together
// - Data doesn't change independently
// Use References when:
// - Data is large
// - Data is shared across documents
// - Data changes independently
// - Need to query data separately
// Array query operators
// $elemMatch - match array elements
db.users.find({
hobbies: { $elemMatch: { $in: ["reading", "gaming"] } }
})
// $size - match array length
db.users.find({ hobbies: { $size: 3 } })
// Array update operators
// $push - add to array
db.users.updateOne(
{ _id: ObjectId("...") },
{ $push: { hobbies: "swimming" } }
)
// $push with $each - add multiple elements
db.users.updateOne(
{ _id: ObjectId("...") },
{ $push: { hobbies: { $each: ["swimming", "cycling"] } } }
)
// $pull - remove from array
db.users.updateOne(
{ _id: ObjectId("...") },
{ $pull: { hobbies: "gaming" } }
)
// $addToSet - add if not exists
db.users.updateOne(
{ _id: ObjectId("...") },
{ $addToSet: { hobbies: "reading" } }
)
// Array position operators
// $ - update first matching element
db.users.updateOne(
{ "scores": { $gt: 80 } },
{ $set: { "scores.$": 85 } }
)
// Array with objects
{
"_id": ObjectId("..."),
"name": "John Doe",
"skills": [
{ "name": "JavaScript", "level": "expert" },
{ "name": "Python", "level": "intermediate" },
{ "name": "MongoDB", "level": "beginner" }
]
}
// Query array objects
db.users.find({
"skills": {
$elemMatch: {
"name": "JavaScript",
"level": "expert"
}
}
})
// Update array objects
db.users.updateOne(
{ "skills.name": "JavaScript" },
{ $set: { "skills.$.level": "master" } }
)
// Array aggregation
db.users.aggregate([
{ $unwind: "$hobbies" },
{ $group: { _id: "$hobbies", count: { $sum: 1 } } },
{ $sort: { count: -1 } }
])
// Create collection with validation
db.createCollection("users", {
validator: {
$jsonSchema: {
bsonType: "object",
required: ["name", "email", "age"],
properties: {
name: {
bsonType: "string",
description: "Name must be a string"
},
email: {
bsonType: "string",
pattern: "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$",
description: "Email must be valid format"
},
age: {
bsonType: "int",
minimum: 0,
maximum: 120,
description: "Age must be between 0 and 120"
},
phone: {
bsonType: "string",
pattern: "^\\+?[1-9]\\d{1,14}$",
description: "Phone must be valid format"
}
}
}
},
validationLevel: "strict",
validationAction: "error"
})
// Add validation to existing collection
db.runCommand({
collMod: "users",
validator: {
$jsonSchema: {
bsonType: "object",
required: ["name", "email"],
properties: {
name: { bsonType: "string" },
email: { bsonType: "string" }
}
}
}
})
// Complex validation example
db.createCollection("products", {
validator: {
$jsonSchema: {
bsonType: "object",
required: ["name", "price", "category"],
properties: {
name: {
bsonType: "string",
minLength: 1,
maxLength: 100
},
price: {
bsonType: "double",
minimum: 0
},
category: {
enum: ["electronics", "clothing", "books", "food"]
},
tags: {
bsonType: "array",
items: { bsonType: "string" },
maxItems: 10
},
inStock: {
bsonType: "bool"
}
}
}
}
})
// Basic transaction
const session = db.getMongo().startSession();
session.startTransaction();
try {
// Transfer money between accounts
db.accounts.updateOne(
{ _id: ObjectId("account1"), balance: { $gte: 100 } },
{ $inc: { balance: -100 } },
{ session }
);
db.accounts.updateOne(
{ _id: ObjectId("account2") },
{ $inc: { balance: 100 } },
{ session }
);
// Commit transaction
await session.commitTransaction();
} catch (error) {
// Abort transaction on error
await session.abortTransaction();
throw error;
} finally {
session.endSession();
}
// Transaction with options
const session = db.getMongo().startSession({
defaultTransactionOptions: {
readConcern: { level: "snapshot" },
writeConcern: { w: "majority" },
readPreference: "primary"
}
});
// Multi-collection transaction
session.startTransaction();
try {
// Update user
db.users.updateOne(
{ _id: ObjectId("user1") },
{ $inc: { balance: -50 } },
{ session }
);
// Create order
db.orders.insertOne({
userId: ObjectId("user1"),
amount: 50,
items: ["product1", "product2"]
}, { session });
// Update inventory
db.inventory.updateOne(
{ productId: "product1" },
{ $inc: { stock: -1 } },
{ session }
);
await session.commitTransaction();
} catch (error) {
await session.abortTransaction();
throw error;
} finally {
session.endSession();
}
# Backup entire database
mongodump --db myapp --out /backup/path
# Backup specific collection
mongodump --db myapp --collection users --out /backup/path
# Backup with authentication
mongodump --uri "mongodb://username:password@host:port/myapp" --out /backup/path
# Restore entire database
mongorestore --db myapp /backup/path/myapp
# Restore specific collection
mongorestore --db myapp --collection users /backup/path/myapp/users.bson
# Restore with authentication
mongorestore --uri "mongodb://username:password@host:port/myapp" /backup/path/myapp
# Export to JSON
mongoexport --db myapp --collection users --out users.json
# Export to CSV
mongoexport --db myapp --collection users --type=csv --fields name,email,age --out users.csv
# Import from JSON
mongoimport --db myapp --collection users --file users.json
# Import from CSV
mongoimport --db myapp --collection users --type=csv --headerline --file users.csv
# Backup with compression
mongodump --db myapp --gzip --out /backup/path
# Restore compressed backup
mongorestore --gzip --db myapp /backup/path/myapp
# Backup with query filter
mongodump --db myapp --collection users --query '{"age": {"$gte": 18}}' --out /backup/path
# Automated backup script
#!/bin/bash
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_DIR="/backup/mongodb"
mongodump --db myapp --out "$BACKUP_DIR/backup_$DATE"
tar -czf "$BACKUP_DIR/backup_$DATE.tar.gz" "$BACKUP_DIR/backup_$DATE"
rm -rf "$BACKUP_DIR/backup_$DATE"
// Atlas connection string
mongodb+srv://username:password@cluster.mongodb.net/database?retryWrites=true&w=majority
// Connect to Atlas
mongosh "mongodb+srv://username:password@cluster.mongodb.net/myapp"
// Atlas connection options
const uri = "mongodb+srv://username:password@cluster.mongodb.net/myapp?retryWrites=true&w=majority";
const client = new MongoClient(uri, {
useNewUrlParser: true,
useUnifiedTopology: true,
maxPoolSize: 10,
serverSelectionTimeoutMS: 5000,
socketTimeoutMS: 45000
});
// Atlas features
// - Automatic backups
// - Point-in-time recovery
// - Global clusters
// - Auto-scaling
// - Monitoring and alerts
// - Data lake
// - Charts (visualization)
// Atlas CLI
atlas cluster create myCluster --provider AWS --region us-east-1 --tier M10
atlas cluster list
atlas cluster pause myCluster
atlas cluster resume myCluster
atlas cluster delete myCluster
// Atlas backup
atlas backup create --clusterName myCluster
atlas backup list --clusterName myCluster
atlas backup restore --clusterName myCluster --backupId backupId
// Create user
use admin
db.createUser({
user: "appuser",
pwd: "securepassword",
roles: [
{ role: "readWrite", db: "myapp" },
{ role: "read", db: "reports" }
]
})
// Create user in specific database
use myapp
db.createUser({
user: "appuser",
pwd: "securepassword",
roles: ["readWrite"]
})
// Built-in roles
// read - Read data only
// readWrite - Read and write data
// dbAdmin - Database administration
// userAdmin - User management
// clusterAdmin - Cluster administration
// root - Superuser
// Create custom role
use admin
db.createRole({
role: "appManager",
privileges: [
{
resource: { db: "myapp", collection: "users" },
actions: ["find", "insert", "update"]
},
{
resource: { db: "myapp", collection: "orders" },
actions: ["find", "insert", "update", "delete"]
}
],
roles: []
})
// Assign role to user
use admin
db.grantRolesToUser("appuser", [
{ role: "appManager", db: "admin" }
])
// List users
use admin
db.getUsers()
// List roles
use admin
db.getRoles()
// Drop user
use admin
db.dropUser("appuser")
// Drop role
use admin
db.dropRole("appManager")
// Authentication methods
// 1. Username/Password
mongosh --username appuser --password securepassword --authenticationDatabase admin
// 2. Connection string
mongodb://appuser:securepassword@localhost:27017/myapp?authSource=admin
// 3. Environment variables
export MONGO_USERNAME=appuser
export MONGO_PASSWORD=securepassword
mongosh --username $MONGO_USERNAME --password $MONGO_PASSWORD
# Initialize replica set
mongod --replSet "rs0" --port 27017
# Connect to primary and initiate
mongosh
rs.initiate({
_id: "rs0",
members: [
{ _id: 0, host: "localhost:27017" },
{ _id: 1, host: "localhost:27018" },
{ _id: 2, host: "localhost:27019" }
]
})
# Start secondary nodes
mongod --replSet "rs0" --port 27018 --dbpath /data/db1
mongod --replSet "rs0" --port 27019 --dbpath /data/db2
# Check replica set status
rs.status()
# Check replica set configuration
rs.conf()
# Add member to replica set
rs.add("localhost:27020")
# Remove member from replica set
rs.remove("localhost:27020")
# Force reconfiguration
rs.reconfig({
_id: "rs0",
members: [
{ _id: 0, host: "localhost:27017" },
{ _id: 1, host: "localhost:27018" },
{ _id: 2, host: "localhost:27019", priority: 0 }
]
})
# Connect to replica set
mongosh "mongodb://localhost:27017,localhost:27018,localhost:27019/?replicaSet=rs0"
# Read preferences
// Primary (default)
db.users.find().readPref("primary")
// Secondary
db.users.find().readPref("secondary")
// Nearest
db.users.find().readPref("nearest")
// Primary preferred
db.users.find().readPref("primaryPreferred")
// Secondary preferred
db.users.find().readPref("secondaryPreferred")
# Start config servers
mongod --configsvr --dbpath /data/configdb --port 27019
mongod --configsvr --dbpath /data/configdb2 --port 27020
mongod --configsvr --dbpath /data/configdb3 --port 27021
# Start shard servers
mongod --shardsvr --dbpath /data/shard1 --port 27017
mongod --shardsvr --dbpath /data/shard2 --port 27018
# Start mongos (query router)
mongos --configdb configReplSet/localhost:27019,localhost:27020,localhost:27021 --port 27016
# Connect to mongos and add shards
mongosh --port 27016
sh.addShard("localhost:27017")
sh.addShard("localhost:27018")
# Enable sharding for database
sh.enableSharding("myapp")
# Enable sharding for collection with shard key
sh.shardCollection("myapp.users", { "userId": 1 })
# Check sharding status
sh.status()
# Check shard distribution
db.users.getShardDistribution()
# Shard key considerations
// Good shard keys
{ "userId": 1 } // High cardinality
{ "country": 1, "userId": 1 } // Compound key
// Bad shard keys
{ "age": 1 } // Low cardinality
{ "timestamp": 1 } // Monotonic (all writes to one shard)
# Balancer operations
sh.startBalancer()
sh.stopBalancer()
sh.isBalancerRunning()
# Move chunks manually
sh.moveChunk("myapp.users", { "userId": 1000 }, "shard1")
// Query analysis with explain()
db.users.find({ age: { $gt: 25 } }).explain("executionStats")
// Analyze query performance
db.users.find({ email: "john@example.com" }).explain("allPlansExecution")
// Check if index is used
db.users.find({ age: { $gt: 25 } }).explain("queryPlanner")
// Database profiler
// Enable profiler
db.setProfilingLevel(2) // Log all operations
// Set profiler level
db.setProfilingLevel(1, { slowms: 100 }) // Log slow operations (>100ms)
// Check profiler status
db.getProfilingStatus()
// View profiler results
db.system.profile.find().sort({ ts: -1 }).limit(10)
// Disable profiler
db.setProfilingLevel(0)
// Index usage statistics
db.users.aggregate([
{ $indexStats: {} }
])
// Collection statistics
db.users.stats()
// Database statistics
db.stats()
// Performance optimization tips
// 1. Use proper indexes
db.users.createIndex({ email: 1 })
db.users.createIndex({ age: 1, city: 1 })
// 2. Use projection to limit fields
db.users.find({}, { name: 1, email: 1, _id: 0 })
// 3. Use limit and skip efficiently
db.users.find().sort({ createdAt: -1 }).limit(10)
// 4. Use covered queries (index contains all fields)
db.users.find({ age: { $gt: 25 } }, { age: 1, _id: 0 })
// 5. Use aggregation for complex queries
db.users.aggregate([
{ $match: { age: { $gt: 25 } } },
{ $group: { _id: "$city", count: { $sum: 1 } } }
])
// 6. Monitor slow queries
db.system.profile.find({ millis: { $gt: 100 } }).sort({ ts: -1 })
// 7. Use connection pooling
const client = new MongoClient(uri, {
maxPoolSize: 10,
minPoolSize: 5,
maxIdleTimeMS: 30000
});
// Install Mongoose
npm install mongoose
// Connect to MongoDB
const mongoose = require('mongoose');
mongoose.connect('mongodb://localhost:27017/myapp', {
useNewUrlParser: true,
useUnifiedTopology: true
});
// Define Schema
const userSchema = new mongoose.Schema({
name: {
type: String,
required: true,
trim: true
},
email: {
type: String,
required: true,
unique: true,
lowercase: true
},
age: {
type: Number,
min: 0,
max: 120
},
isActive: {
type: Boolean,
default: true
},
createdAt: {
type: Date,
default: Date.now
}
});
// Create Model
const User = mongoose.model('User', userSchema);
// CRUD Operations
// Create
const user = new User({
name: 'John Doe',
email: 'john@example.com',
age: 30
});
await user.save();
// Or use create
const user = await User.create({
name: 'Jane Smith',
email: 'jane@example.com',
age: 25
});
// Read
const users = await User.find({ age: { $gt: 25 } });
const user = await User.findOne({ email: 'john@example.com' });
const user = await User.findById(userId);
// Update
await User.updateOne(
{ email: 'john@example.com' },
{ $set: { age: 31 } }
);
await User.findByIdAndUpdate(userId, { age: 31 });
// Delete
await User.deleteOne({ email: 'john@example.com' });
await User.findByIdAndDelete(userId);
// Middleware (Hooks)
userSchema.pre('save', function(next) {
this.updatedAt = new Date();
next();
});
userSchema.post('save', function(doc) {
console.log('User saved:', doc.name);
});
// Virtual fields
userSchema.virtual('fullName').get(function() {
return `${this.firstName} ${this.lastName}`;
});
// Instance methods
userSchema.methods.getAge = function() {
return new Date().getFullYear() - this.birthYear;
};
// Static methods
userSchema.statics.findByEmail = function(email) {
return this.findOne({ email: email });
};
// Query helpers
userSchema.query.byAge = function(age) {
return this.where({ age: age });
};
// Usage
const users = await User.find().byAge(30);
# Start MongoDB server
mongod --dbpath /data/db
mongod --config /etc/mongod.conf
# Connect to MongoDB
mongosh
mongosh "mongodb://localhost:27017"
mongosh "mongodb://username:password@host:port/database"
# Basic shell commands
show dbs # List databases
use myapp # Switch database
show collections # List collections
show users # List users
show roles # List roles
show profile # Show profiler status
# Database operations
db.dropDatabase() # Delete current database
db.stats() # Database statistics
db.getName() # Current database name
# Collection operations
db.createCollection("users") # Create collection
db.users.drop() # Delete collection
db.users.stats() # Collection statistics
db.users.renameCollection("newusers") # Rename collection
# User management
db.createUser({...}) # Create user
db.dropUser("username") # Delete user
db.getUsers() # List users
db.grantRolesToUser("user", [...]) # Grant roles
# Index operations
db.users.createIndex({...}) # Create index
db.users.dropIndex("index_name") # Drop index
db.users.getIndexes() # List indexes
db.users.reIndex() # Rebuild indexes
# Backup and restore
mongodump --db myapp --out /backup
mongorestore --db myapp /backup/myapp
mongoexport --db myapp --collection users --out users.json
mongoimport --db myapp --collection users --file users.json
# Monitoring and profiling
db.setProfilingLevel(1, {slowms: 100}) # Enable profiler
db.system.profile.find() # View profiler results
db.currentOp() # Current operations
db.killOp(opId) # Kill operation
# Replica set commands
rs.status() # Replica set status
rs.conf() # Replica set configuration
rs.add("host:port") # Add member
rs.remove("host:port") # Remove member
rs.stepDown() # Step down primary
# Sharding commands
sh.status() # Sharding status
sh.addShard("host:port") # Add shard
sh.enableSharding("db") # Enable sharding
sh.shardCollection("db.collection", {key: 1}) # Shard collection
# Utility commands
db.runCommand({ping: 1}) # Ping server
db.runCommand({serverStatus: 1}) # Server status
db.runCommand({dbStats: 1}) # Database stats
db.runCommand({collStats: "users"}) # Collection stats
# Help and documentation
help # General help
db.help() # Database help
db.users.help() # Collection help