🍃 MongoDB Tutorial

MongoDB Indexing Basics: Why Indexes Matter and createIndex()

Learn what indexing is in MongoDB, why it dramatically speeds up queries, and how to create your first index with createIndex() — with an explain() comparison.

Indexing in MongoDB

Without an index, MongoDB must perform a collection scan — checking every single document to find the ones that match your query. As a collection grows into the millions of documents, this gets slow fast.

Indexes are special data structures that store a small amount of information about a field's values, letting MongoDB jump straight to matching documents instead of scanning everything.

  • Every document automatically gets a default index on _id.
  • The _id index cannot be dropped — attempting to do so throws an error.

Creating an Index

db.COLLECTION_NAME.createIndex({ KEY: 1 })

1 means ascending order, -1 means descending — for a single-field index, either works the same for equality/range lookups.

db.student.createIndex({ roll: 1 })
// roll_1

Seeing the Difference: explain("executionStats")

Before creating the index, a query has to scan the whole collection:

db.student.find({ roll: { $gte: 3 } }).explain("executionStats")
// stage: 'COLLSCAN'
// totalDocsExamined: 5   <- scanned every document

After creating the index on roll, the same query uses it instead:

db.student.createIndex({ roll: 1 })

db.student.find({ roll: { $gte: 3 } }).explain("executionStats")
// stage: 'IXSCAN'
// totalKeysExamined: 3
// totalDocsExamined: 3   <- only examined the matching documents

COLLSCAN → IXSCAN is exactly the improvement an index is meant to provide.

Common Errors & Troubleshooting

  • Creating an index and seeing no speed improvement — check explain("executionStats") to confirm it actually switched from COLLSCAN to IXSCAN; sometimes a query's structure (like using $where or a leading wildcard regex) prevents any index from being used at all.
  • createIndex() seeming to hang on a huge collection — by default index builds can block other operations; on a large production collection, consider building in the background (modern MongoDB versions build indexes in a non-blocking way by default, but very large builds still take real time).
  • Forgetting the _id index already exists — you don't need to (and can't) create an index on _id yourself — it's automatic and can never be dropped.

Key Takeaways

  • No index means a full collection scan on every query — indexes let MongoDB skip straight to matches.
  • _id always has a default index that can never be dropped.
  • explain("executionStats") is the best way to prove an index is actually being used.