Skip to content

How to Create and Optimize MongoDB Indexes

DodaTech 2 min read

In this tutorial, you'll learn about How to Create and Optimize MongoDB Indexes. We cover key concepts, practical examples, and best practices.

The Problem

Your MongoDB queries are slow, scanning many documents, and explain() shows COLLSCAN (collection scan) instead of IXSCAN (index scan), because the queried fields lack indexes.

Quick Fix

Check Query Execution with explain()

mongosh mydb --eval '
db.orders.find({ status: "pending" }).explain("executionStats")
'
# {
#   "queryPlanner": {
#     "winningPlan": {
#       "stage": "COLLSCAN"
#     }
#   },
#   "executionStats": {
#     "totalDocsExamined": 50000
#   }
# }

COLLSCAN means every document is read. totalDocsExamined shows the scan cost. An index should reduce this to match nReturned.

Create a Single-Field Index

mongosh mydb --eval '
db.orders.createIndex({ status: 1 })
'
# status_1

Create an ascending (1) index on the status field. Re-run explain() to confirm the stage changes from COLLSCAN to IXSCAN.

Create a Compound Index for Multi-Field Queries

mongosh mydb --eval '
db.orders.createIndex({ status: 1, created_at: -1 })
'
# status_1_created_at_-1

A compound index on (status, created_at) supports queries that filter by both fields. Order the fields by selectivity (most selective first) and sort order.

List Existing Indexes and Drop Unused Ones

mongosh mydb --eval '
db.orders.getIndexes()
'
# [
#   { "v": 2, "key": { "_id": 1 }, "name": "_id_" }, "#   { "v": 2", "key": { "status": 1 }, "name": "status_1" }
# ]

mongosh mydb --eval '
db.orders.dropIndex("old_unused_index")
'
# { "nIndexesWas": 3, "ok": 1 }

Use getIndexes() to review all indexes and dropIndex() to remove unused ones. Each unnecessary index slows down writes and uses memory.

Use explain() Output to Compare Index Candidates

mongosh mydb --eval '
db.orders.find({ status: "pending", created_at: { $gt: ISODate("2026-01-01") } })
    .sort({ created_at: -1 })
    .explain("executionStats")
'

Before creating an index, test different index candidates with explain(). Compare totalDocsExamined, totalKeysExamined, and executionTimeMillis across different index strategies to choose the optimal one.

Additional Troubleshooting

# Check the error message and stack trace for more context
echo "Review the full error output to identify the root cause"

If the above steps do not resolve the issue, examine the complete error message and stack trace. Often the key detail is in the middle of the traceback rather than the final line. Search for the error message in the project documentation or issue tracker for additional solutions.

Monitor Index Usage with $indexStats

mongosh mydb --eval '
db.orders.aggregate([ { \$indexStats: {} } ])
'

The $indexStats aggregation stage returns access statistics for each index, including the number of operations and the last access time. Use this to identify indexes that are never used and should be removed.

Prevention

  • Run explain("executionStats") on slow queries before adding indexes
  • Create indexes that match your query patterns (equality filters, sort fields, range queries)
  • Use MongoDB Compass or $indexStats to monitor index usage over time
  • Limit indexes per collection to 5–10 to keep write performance healthy

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro