Indexes in MongoDB
Indexes improve query performance by allowing MongoDB to quickly locate documents that match a query condition, rather than scanning every document in the collection.
Think of an index as a “table of contents” for your collection — it lets MongoDB jump directly to the relevant documents.
The Default _id Index
Every collection automatically creates an index on the _id field.
db.products.getIndexes()
Will give an ouput like:
[
{ v: 2, key: { _id: 1 }, name: "_id_" }
]
This index ensures that every _id is unique and makes lookups by _id very fast.
Creating a Single Field Index
You can create an index on any field to improve read performance for queries using that field.
db.products.createIndex({ price: 1 })
1= ascending order-1= descending order
This index helps queries like:
db.products.find({ price: { $lt: 500 } })
Compound Indexes
You can also create indexes on multiple fields. The order of the fields matters.
db.products.createIndex({ brand: 1, price: -1 })
This index supports queries that use both brand and price, for example:
db.products.find({ brand: "Apple" }).sort({ price: -1 })
Why Index Field Order Matters
When you create a compound index, the order of the fields determines how MongoDB can use it for queries. Example:
db.products.createIndex({ brand: 1, price: -1 })
This index is sorted first by brand (A–Z) and, within each brand, by price (high → low).
Think of it like a phone book sorted first by last name and then by first name: you can quickly find all people with the same last name, but you can’t look up everyone named “John” efficiently without knowing their last name first.
The Left-Prefix Rule
MongoDB follows the left-prefix rule: An index can only be used efficiently starting from its leftmost field.
So for the index { brand: 1, price: -1 }:
| Query | Can use the index? | Reason |
|---|---|---|
db.products.find({ brand: "Apple" }) | ✅ | Uses the first field (brand) |
db.products.find({ brand: "Apple" }).sort({ price: -1 }) | ✅ | Uses both fields |
db.products.find({ price: { $gt: 500 } }) | ❌ | Skips the first field (brand) |
If you often query by price alone, you should create a separate index:
db.products.createIndex({ price: -1 })
Viewing and Dropping Indexes
List all indexes in a collection:
db.products.getIndexes()
Drop an index by name:
db.products.dropIndex("brand_1_price_-1")
The Query Planner
MongoDB automatically decides whether to use an index. To see how a query is executed, use explain():
db.products.find({ price: { $lt: 500 } }).explain("executionStats")
If you see "IXSCAN", the index is being used. If you see "COLLSCAN", MongoDB is scanning the whole collection — which is slower.
Trade-offs
Indexes are powerful, but they have costs:
| Advantage | Disadvantage |
|---|---|
| Much faster read operations | Slightly slower writes (because indexes must be updated) |
| Enable efficient sorting and range queries | Consume extra disk space |
| Allow unique constraints | Require careful design to match query patterns |
Practice Questions
🧠 1. What does MongoDB automatically index for each document?
- A) Every string field
- B) The _id field
- C) All numeric fields
- D) The price field
Click to reveal answer
Correct: **B**
🧠 2. Which query benefits from the following index?
db.products.createIndex({ brand: 1, price: -1 })
- A)
db.products.find({ brand: "Apple" }).sort({ price: -1 }) - B)
db.products.find({ price: { $gt: 500 } }) - C)
db.products.find({ name: "MacBook" }) - D) None of the above
Click to reveal answer
Correct: **A**
🧠 3. Why can too many indexes slow down writes?
Click to reveal answer
Because MongoDB must update every relevant index whenever a document is inserted or modified.
🧠 4. How can you check whether a query uses an index?