Skip to content

MongoDB - Indexing

Indexes are crucial for database performance. Think of them like the index at the back of a book: instead of reading every page to find a topic, you look it up in the index and go directly to the right page. Similarly, without indexes, MongoDB must perform a collection scan—reading every document—to find matching query results. This is inefficient, especially for large datasets.

An index is a special data structure that stores a small, ordered portion of a collection’s data, enabling MongoDB to execute queries much more efficiently.

You use the createIndex() method to create an index on a collection. You specify the field to index and the sort order: 1 for ascending and -1 for descending.

Creates an index on a single field.

// Creates an ascending index on the 'username' field in the 'users' collection
db.users.createIndex({ "username": 1 });

Creates an index on multiple fields. The order of fields matters and should match your common query patterns.

// Creates a compound index on 'category' (ascending) and 'rating' (descending)
db.products.createIndex({ "category": 1, "rating": -1 });

The createIndex() method accepts an optional options document. Here are some of the most common options:

OptionTypeDescription
uniqueBooleanEnsures that the indexed field(s) have a unique value. If true, MongoDB will reject inserts or updates that cause a duplicate. Default is false.
nameStringA custom name for the index. If not specified, MongoDB generates a name based on the indexed keys and their orders.
backgroundBooleanDEPRECATED (now default behavior). In modern MongoDB versions, all foreground index builds are fast. This option is kept for compatibility but has no effect.
partialFilterExpressionDocumentCreates a partial index. The index only includes documents that match the specified filter expression, saving space and improving performance.
expireAfterSecondsIntegerCreates a TTL (Time-To-Live) index. MongoDB will automatically delete documents from the collection after the specified number of seconds has passed. Only works on a date field.
// Create a unique, named index on the 'email' field
db.users.createIndex(
{ "email": 1 },
{ unique: true, name: "unique_email_index" }
);

This method returns an array of documents describing all indexes on a collection.

> db.users.getIndexes()
[
{
"v" : 2,
"key" : { "_id" : 1 },
"name" : "_id_"
},
{
"v" : 2,
"key" : { "email" : 1 },
"unique" : true,
"name" : "unique_email_index"
}
]

You can drop a specific index by providing its name or key specification. Dropping by name is the recommended practice.

// Drop the index by its name
db.users.dropIndex("unique_email_index");
// Alternatively, drop by its key pattern
db.users.dropIndex({ "email": 1 });

The dropIndexes() method without arguments is used to drop all non-_id indexes on a collection. Use with caution.

To verify if your query is using an index, you can append the explain() method to your cursor. It provides detailed information on the query execution plan.

> db.users.find({ email: "test@example.com" }).explain("executionStats")

In the output, look for the winningPlan.stage. If it shows IXSCAN (Index Scan), your query used an index. If it shows COLLSCAN (Collection Scan), it did not, and you may need to create a suitable index.