MongoDB Indexing
Speed up queries with efficient database indexes
⚡ What is Indexing?
Indexes are special data structures that store a small portion of data in an easy-to-traverse form. They dramatically improve query performance by reducing the number of documents MongoDB must scan.
// Create an index on email field
db.users.createIndex({ email: 1 })
Index Types
MongoDB supports various index types for different use cases. Choose the right index type based on your query patterns and data structure.
Single Field
Index on one field
db.users.createIndex({ email: 1 })
Compound
Index on multiple fields
db.users.createIndex({ city: 1, age: -1 })
Unique
Ensures field uniqueness
db.users.createIndex({ email: 1 }, { unique: true })
Text
Full-text search index
db.posts.createIndex({ content: "text" })
🔹 Single Field Indexes
Single field indexes are the most basic type. They index one field in ascending (1) or descending (-1) order.
🔸 Create Single Field Index
// Index on email field (ascending)
db.users.createIndex({ email: 1 })
// Index on age field (descending)
db.users.createIndex({ age: -1 })
// Index on nested field
db.users.createIndex({ "address.city": 1 })
When to Use:
- Frequently queried fields
- Fields used in sorting
- Fields with high cardinality (many unique values)
Performance Impact:
Without Index: Scans 100,000 documents With Index: Scans 1 document Speed Improvement: 100,000x faster!
🔹 Compound Indexes
Compound indexes index multiple fields together. The order of fields matters - queries can use the index from left to right.
🔸 Create Compound Index
// Index on city and age
db.users.createIndex({ city: 1, age: -1 })
// Index on category, price, and rating
db.products.createIndex({
category: 1,
price: -1,
rating: -1
})
Index Prefix Rule:
A compound index on { a: 1, b: 1, c: 1 } can support queries on:
- { a: 1 }
- { a: 1, b: 1 }
- { a: 1, b: 1, c: 1 }
But NOT on { b: 1 } or { c: 1 } alone
🔸 Query Examples
// These queries use the index { city: 1, age: -1 }
db.users.find({ city: "New York" })
db.users.find({ city: "New York", age: { $gt: 25 } })
// This query does NOT use the index efficiently
db.users.find({ age: { $gt: 25 } })
🔹 Unique Indexes
Unique indexes ensure that indexed fields don't contain duplicate values. MongoDB rejects documents with duplicate values for the indexed field.
🔸 Create Unique Index
// Ensure email is unique
db.users.createIndex({ email: 1 }, { unique: true })
// Compound unique index
db.users.createIndex(
{ username: 1, provider: 1 },
{ unique: true }
)
// Unique index on array field
db.products.createIndex({ sku: 1 }, { unique: true })
Example:
// First insert succeeds
db.users.insertOne({ email: "[email protected]", name: "John" })
// Second insert fails (duplicate email)
db.users.insertOne({ email: "[email protected]", name: "Jane" })
// Error: E11000 duplicate key error
🔹 Text Indexes
Text indexes support text search queries on string content. They tokenize and stem text, enabling full-text search capabilities.
🔸 Create Text Index
// Text index on single field
db.posts.createIndex({ content: "text" })
// Text index on multiple fields
db.articles.createIndex({
title: "text",
body: "text",
tags: "text"
})
// Text index with weights
db.posts.createIndex(
{ title: "text", content: "text" },
{ weights: { title: 10, content: 5 } }
)
🔸 Search with Text Index
// Search for "mongodb tutorial"
db.posts.find({ $text: { $search: "mongodb tutorial" } })
// Search for exact phrase
db.posts.find({ $text: { $search: "\"mongodb tutorial\"" } })
// Exclude words with minus sign
db.posts.find({ $text: { $search: "mongodb -sql" } })
Example:
// Search posts about MongoDB
db.posts.find(
{ $text: { $search: "mongodb database" } },
{ score: { $meta: "textScore" } }
).sort({ score: { $meta: "textScore" } })
🔹 Multikey Indexes
Multikey indexes automatically index array fields. MongoDB creates separate index entries for each array element.
🔸 Create Multikey Index
// Index on array field
db.posts.createIndex({ tags: 1 })
// Query uses multikey index
db.posts.find({ tags: "mongodb" })
db.posts.find({ tags: { $in: ["mongodb", "database"] } })
Example:
// Document with array field
{ "_id": 1, "title": "Post", "tags": ["mongodb", "database", "nosql"] }
// Index creates entries for:
// "mongodb" -> document 1
// "database" -> document 1
// "nosql" -> document 1
🔹 Index Management
View, analyze, and remove indexes to optimize database performance.
🔸 View Indexes
// List all indexes on collection
db.users.getIndexes()
// View index sizes
db.users.stats().indexSizes
🔸 Drop Indexes
// Drop specific index
db.users.dropIndex("email_1")
// Drop index by specification
db.users.dropIndex({ email: 1 })
// Drop all indexes (except _id)
db.users.dropIndexes()
🔸 Analyze Query Performance
// Explain query execution
db.users.find({ email: "[email protected]" }).explain("executionStats")
// Check if index is used
db.products.find({
category: "Electronics",
price: { $lt: 1000 }
}).explain("executionStats")
🔹 Index Properties
Customize index behavior with special properties.
🔸 Sparse Indexes
// Only index documents with the field
db.users.createIndex(
{ phone: 1 },
{ sparse: true }
)
🔸 TTL Indexes
// Auto-delete documents after 30 days
db.sessions.createIndex(
{ createdAt: 1 },
{ expireAfterSeconds: 2592000 }
)
🔸 Partial Indexes
// Index only active users
db.users.createIndex(
{ email: 1 },
{
partialFilterExpression: {
status: "active"
}
}
)
🔹 Index Best Practices
Follow these guidelines for optimal index performance:
✅ Do:
- Index fields used frequently in queries
- Create compound indexes for multi-field queries
- Use unique indexes to enforce data integrity
- Monitor index usage with explain()
- Place most selective fields first in compound indexes
❌ Don't:
- Create too many indexes (slows writes)
- Index low-cardinality fields (few unique values)
- Index fields that are rarely queried
- Forget to drop unused indexes
- Index every field "just in case"
🔹 Practical Examples
Real-world indexing scenarios:
Example 1: E-commerce Product Search
// Compound index for product filtering
db.products.createIndex({
category: 1,
price: 1,
rating: -1
})
// Text index for search
db.products.createIndex({
name: "text",
description: "text"
})
// Unique index for SKU
db.products.createIndex(
{ sku: 1 },
{ unique: true }
)
Example 2: User Authentication System
// Unique index on email
db.users.createIndex(
{ email: 1 },
{ unique: true }
)
// Index for login queries
db.users.createIndex({ email: 1, password: 1 })
// TTL index for password reset tokens
db.resetTokens.createIndex(
{ createdAt: 1 },
{ expireAfterSeconds: 3600 }
)
Example 3: Social Media Posts
// Compound index for user timeline
db.posts.createIndex({
userId: 1,
createdAt: -1
})
// Text index for post search
db.posts.createIndex({ content: "text" })
// Multikey index for hashtags
db.posts.createIndex({ hashtags: 1 })