MongoDB Indexes
An index in MongoDB works exactly like the index at the back of a textbook. Instead of flipping through every page to find a topic, the reader goes to the index, finds the topic, and jumps directly to the right page. Similarly, a MongoDB index allows the database to find documents quickly without scanning every document in a collection.
Without an index, MongoDB performs a collection scan — it reads every document from start to finish to find matches. For small collections, this is acceptable. For collections with thousands or millions of documents, it becomes very slow.
Why Indexes Matter
Consider a collection with 1 million product documents. A query like db.products.find({ category: "Electronics" }) without an index forces MongoDB to check all 1 million documents one by one. With an index on the category field, MongoDB jumps directly to matching documents — the difference in speed is dramatic.
The Default _id Index
Every MongoDB collection automatically gets an index on the _id field when it is created. This index is unique and cannot be deleted. It guarantees that no two documents share the same _id value.
Types of Indexes in MongoDB
1. Single Field Index
A single field index is created on one field. It speeds up queries that filter, sort, or look up documents by that field.
db.products.createIndex({ category: 1 })
The 1 means the index is created in ascending order. Using -1 creates a descending index.
After this index exists, any query filtering by category will use the index automatically:
db.products.find({ category: "Electronics" })
2. Compound Index
A compound index is created on two or more fields. It is useful when queries frequently filter or sort by multiple fields together.
db.products.createIndex({ category: 1, price: -1 })
This index works well for queries like: find all Electronics products sorted by price from high to low.
db.products.find({ category: "Electronics" }).sort({ price: -1 })
The order of fields in a compound index matters. An index on { category, price } supports queries that filter by category alone, or by both category and price. It does not support queries that filter only by price without category.
3. Unique Index
A unique index ensures no two documents in a collection can have the same value for a specific field. This is useful for fields like email addresses or usernames that must be unique across all records.
db.users.createIndex({ email: 1 }, { unique: true })
After this index is created, any attempt to insert a document with a duplicate email throws an error:
// First insert — success
db.users.insertOne({ email: "ravi@example.com", name: "Ravi" })
// Second insert with the same email — error
db.users.insertOne({ email: "ravi@example.com", name: "Ravi Kumar" })
// MongoServerError: E11000 duplicate key error
4. Text Index
A text index supports full-text search on string fields. It allows searching for words inside string content, similar to a search engine.
db.articles.createIndex({ title: "text", content: "text" })
After this index is set up, use $text and $search to find documents containing specific words:
db.articles.find({ $text: { $search: "mongodb tutorial" } })
This finds all articles that contain the words "mongodb" or "tutorial" anywhere in the indexed text fields.
5. Multikey Index
A multikey index is automatically created when an index is placed on an array field. MongoDB creates individual index entries for each element in the array.
db.products.createIndex({ tags: 1 })
If a product has tags: ["wireless", "bluetooth", "portable"], MongoDB creates three separate index entries — one for each tag. This allows efficient queries like:
db.products.find({ tags: "bluetooth" })
6. TTL Index (Time To Live)
A TTL index automatically deletes documents after a specified number of seconds. It is useful for temporary data like session records, logs, or one-time tokens that should expire.
db.sessions.createIndex({ createdAt: 1 }, { expireAfterSeconds: 3600 })
This deletes session documents 3600 seconds (1 hour) after the createdAt date value. The field must store a Date type for TTL to work.
7. Sparse Index
A sparse index only includes documents where the indexed field exists. Documents missing the field are excluded from the index entirely.
db.users.createIndex({ phone: 1 }, { sparse: true })
This is helpful when a field is optional and only some documents have it. A sparse index avoids bloating the index with null entries from documents that don't have the field.
Viewing Existing Indexes
db.products.getIndexes()
This lists all indexes on the products collection, including the automatic _id index and any custom ones created.
Dropping an Index
To remove a specific index:
db.products.dropIndex({ category: 1 })
To remove all indexes except _id:
db.products.dropIndexes()
Analyzing Query Performance with explain()
The explain() method reveals how MongoDB executes a query — whether it uses an index or performs a full collection scan.
db.products.find({ category: "Electronics" }).explain("executionStats")
Two key values in the output:
- IXSCAN — Index Scan. MongoDB used an index. Good.
- COLLSCAN — Collection Scan. MongoDB scanned every document. Needs an index.
The output also shows totalDocsExamined — the number of documents MongoDB looked at. A well-indexed query examines only the documents it returns, not the entire collection.
Index Best Practices
Index Fields That Appear in Filters and Sorts
Create indexes on fields that queries frequently use in find() filters or sort() operations.
Avoid Too Many Indexes
Every index speeds up reads but slows down writes. Each time a document is inserted or updated, all related indexes must be updated too. Keep only the indexes that are actually used by active queries.
Use Compound Indexes for Multi-Field Queries
A single compound index on { city, age } is more efficient than two separate indexes on city and age for queries that filter by both fields.
ESR Rule for Compound Index Order
When building compound indexes, follow the ESR rule:
- Equality fields first
- Sort fields next
- Range fields last
Index Type Summary Table
| Index Type | Use Case |
|---|---|
| Single Field | Queries filtering by one field |
| Compound | Queries filtering or sorting by multiple fields |
| Unique | Prevent duplicate values (emails, usernames) |
| Text | Full-text word search on string fields |
| Multikey | Queries on array fields |
| TTL | Auto-delete documents after a time period |
| Sparse | Index only documents that have the field |
Summary
Indexes in MongoDB dramatically improve query performance by allowing the database to locate matching documents without scanning the entire collection. MongoDB provides several index types: single field, compound, unique, text, multikey, TTL, and sparse — each designed for specific use cases. The createIndex() method creates indexes, and explain() helps verify whether a query uses an index. Balancing the right indexes prevents unnecessary overhead during write operations while keeping read performance fast.
