Create MongoDB Indexes

MongoDBBeginner
Practice Now

Introduction

In this lab, you will learn the fundamental techniques for creating and managing indexes in MongoDB. Indexes are crucial for optimizing database performance, as they allow the database to find and retrieve data much faster than scanning every document in a collection. You will practice creating single-field, compound, and unique indexes, analyzing their impact on query performance, and managing their lifecycle. By the end of this lab, you will have a solid understanding of how to use indexes to make your MongoDB queries more efficient.

Create a Single-Field Index

In this first step, you will connect to MongoDB, create a database with a sample collection, and then create your first index on a single field. A single-field index improves performance for queries that filter or sort on that specific field.

First, open the MongoDB Shell by typing mongosh in your terminal. This will connect you to the MongoDB server running in your environment.

mongosh

Once you are inside the MongoDB Shell, you will see a > prompt. Let's create and switch to a new database called indexlab. All subsequent commands in this lab will be run inside this shell unless otherwise noted.

use indexlab

Now, let's insert some sample documents into a new collection named users. This data will be used throughout the lab.

db.users.insertMany([
  { name: "Alice", age: 28, email: "alice@example.com" },
  { name: "Bob", age: 35, email: "bob@example.com" },
  { name: "Charlie", age: 42, email: "charlie@example.com" }
]);

With our data in place, let's create an index on the name field. An index on a single field helps speed up queries that search for documents by that field.

db.users.createIndex({ name: 1 });

In the command above, { name: 1 } specifies that the index should be created on the name field in ascending order. Using -1 would create a descending index.

To verify that the index was created, you can list all indexes for the users collection.

db.users.getIndexes();

You should see two indexes in the output. One is the default _id index created by MongoDB on every collection, and the other is the name_1 index you just created.

[
  { "v": 2, "key": { "_id": 1 }, "name": "_id_" },
  { "v": 2, "key": { "name": 1 }, "name": "name_1" }
]

Build a Compound Index

While single-field indexes are useful, many queries filter on multiple fields. For these cases, a compound index, which includes several fields, can provide a significant performance boost. In this step, you will create a compound index.

Let's continue in the mongosh shell. We will create a compound index on the age and name fields. The order of fields in a compound index is important. MongoDB can use this index to support queries on age alone, or on both age and name.

db.users.createIndex({ age: -1, name: 1 });

This command creates an index that first sorts documents by age in descending order (-1) and then, for documents with the same age, sorts them by name in ascending order (1).

Let's add a few more documents to make our collection more diverse for querying.

db.users.insertMany([
  { name: "David", age: 28, email: "david@example.com" },
  { name: "Eve", age: 35, email: "eve@example.com" }
]);

Now, view the list of indexes again to see your new compound index.

db.users.getIndexes();

The output will now include the age_-1_name_1 index, in addition to the previous ones.

[
  { "v": 2, "key": { "_id": 1 }, "name": "_id_" },
  { "v": 2, "key": { "name": 1 }, "name": "name_1" },
  { "v": 2, "key": { "age": -1, "name": 1 }, "name": "age_-1_name_1" }
]

This compound index will efficiently serve queries that filter or sort by age, or by age and then name.

Create a Unique Index

Indexes can also be used to enforce data integrity. A unique index ensures that the indexed field (or fields) does not contain duplicate values. In this step, you will create a unique index to prevent duplicate email addresses in the users collection.

Let's create a unique index on the email field. This is done by adding the { unique: true } option when creating the index.

db.users.createIndex({ email: 1 }, { unique: true });

Now that the unique index is in place, MongoDB will reject any attempt to insert or update a document if it results in a duplicate value for the email field.

Let's test this. First, try to insert a document with a new, unique email. This should succeed.

db.users.insertOne({ name: "Frank", age: 31, email: "frank@example.com" });

Next, attempt to insert another document with an existing email, such as alice@example.com. This operation will fail. The try...catch block allows you to see the error without being disconnected from the mongosh shell.

try {
  db.users.insertOne({ name: "Fiona", age: 29, email: "alice@example.com" });
} catch (e) {
  print(e);
}

The command will throw an error indicating a duplicate key violation. The output will contain a message like E11000 duplicate key error collection.

You can view your indexes again to see the unique constraint property.

db.users.getIndexes();

Notice the unique: true property on the email_1 index in the output.

[
  ...,
  {
    v: 2,
    key: { email: 1 },
    name: 'email_1',
    unique: true
  }
]

Analyze Index Usage with explain()

Creating indexes is only half the battle; you also need to verify that MongoDB is actually using them for your queries. The explain() method is a powerful tool for this, providing detailed information about how a query is executed. This step will show you how to use explain() to verify that MongoDB is using your existing indexes effectively.

Let's analyze a query that finds users of a certain age. Since we already have the compound index age_-1_name_1 from the previous step, MongoDB can use this index to optimize the query on the age field.

db.users.find({ age: 35 }).explain("executionStats");

In the output, look for the executionStats.stage field inside winningPlan. You should see a value of IXSCAN, which stands for "Index Scan". This indicates that MongoDB is using the existing compound index age_-1_name_1 to quickly locate the relevant documents. You should also see that totalDocsExamined matches the number of documents returned, demonstrating the efficiency of using the compound index.

To better understand how MongoDB chooses indexes, let's also test a query that can benefit from the single-field name index we created earlier.

db.users.find({ name: "Alice" }).explain("executionStats");

This query should also show IXSCAN as the winning plan stage, confirming that MongoDB is using the name_1 index we created in the first step.

View and Drop Indexes

The final part of managing indexes is knowing how to list them and remove them when they are no longer needed. Unused indexes still consume storage and add overhead to write operations, so it is good practice to clean them up.

First, let's get a complete list of all the indexes you have created so far in the users collection.

db.users.getIndexes();

This command provides a comprehensive overview of your current index setup. Suppose you decide that the compound index age_-1_name_1 is no longer necessary. You can remove it using the dropIndex() method, specifying the index name.

db.users.dropIndex("age_-1_name_1");

After running the command, you will receive a confirmation message. To be certain, you can list the indexes one more time to verify that it has been removed.

db.users.getIndexes();

The age_-1_name_1 index should no longer appear in the list.

If you need to remove all custom indexes from a collection (except for the default _id index), you can use the dropIndexes() method. This command is powerful, so use it with care.

// Example: db.users.dropIndexes()

This concludes the basic operations for managing indexes in MongoDB. You can now exit the mongosh shell.

exit;

Summary

In this lab, you have learned the essential skills for working with MongoDB indexes. You started by creating a basic single-field index to speed up simple queries. You then progressed to building a compound index to optimize queries involving multiple fields. You also learned how to enforce data integrity by creating a unique index. Furthermore, you used the explain() method to analyze query plans and confirm that your indexes were being used effectively, observing the performance difference between a collection scan and an index scan. Finally, you practiced managing your indexes by listing and dropping them. Mastering these indexing techniques is a critical step toward building fast and scalable applications with MongoDB.