Why Indexes Matter
Without indexes, MongoDB must scan every document in a collection to find matches -- known as a collection scan. Indexes store a sorted subset of fields in a B-tree structure, allowing MongoDB to locate documents efficiently. A well-designed index can reduce query time from seconds to milliseconds.
Creating a Single-Field Index
The simplest index type covers a single field. Use 1 for ascending and -1 for descending:
// Create an ascending index on the "email" field
db.users.createIndex({ email: 1 })
// Create a descending index on "createdAt"
db.orders.createIndex({ createdAt: -1 })
// Unique index -- prevents duplicate values
db.users.createIndex({ email: 1 }, { unique: true })Compound Indexes
Compound indexes cover multiple fields and support queries that filter or sort on those fields:
// Index for queries that filter by status and sort by date
db.orders.createIndex({ status: 1, createdAt: -1 })
// This index supports:
db.orders.find({ status: "completed" }).sort({ createdAt: -1 })
db.orders.find({ status: "pending" })The order of fields in a compound index matters. Follow the ESR rule: Equality fields first, then Sort fields, then Range fields.
Multikey Indexes
MongoDB automatically creates multikey indexes when the indexed field contains an array:
// If "tags" is an array, this becomes a multikey index
db.articles.createIndex({ tags: 1 })
// Efficiently supports queries like:
db.articles.find({ tags: "javascript" })
db.articles.find({ tags: { $in: ["react", "vue"] } })Analyzing Query Performance
Use explain() to see how MongoDB executes a query and whether it uses an index:
// Check if the query uses an index
db.users.find({ email: "alice@example.com" }).explain("executionStats")
// Look for these key fields in the output:
// - winningPlan.stage: "IXSCAN" (good) vs "COLLSCAN" (bad)
// - executionStats.totalDocsExamined
// - executionStats.executionTimeMillisManaging Indexes
List, inspect, and remove indexes as your application evolves:
// List all indexes on a collection
db.users.getIndexes()
// Drop a specific index by name
db.users.dropIndex("email_1")
// Drop all indexes except _id
db.users.dropIndexes()
// Create index in background (default in MongoDB 4.2+)
db.orders.createIndex(
{ customerId: 1 },
{ name: "idx_customer" }
)Key Takeaways
- Indexes dramatically improve read performance but add overhead to writes.
- Use compound indexes following the ESR rule (Equality, Sort, Range).
- Always verify index usage with
explain(). - Remove unused indexes to save storage and write overhead.
Try this query in UnifySQL
Write, optimize, and collaborate on MongoDB queries with AI assistance.
Start Free