🔍 Optimising MongoDB Queries with Indexes

Indexes are vital for improving MongoDB query performance, but their variety can be a bit confusing. Let's explore the world of MongoDB Indexes!

Rohit Nair
Rohit Nair
- 6 min read
🔍 Optimising MongoDB Queries with Indexes
🔍 Optimising MongoDB Queries with Indexes

Indexes are essential for improving query performance in MongoDB, but with so many types available, it can be challenging to know where to start. This guide explores the different types of indexes—unique, non-unique, sparse, partial, full-text, and compound—and provides best practices to optimize your database performance effectively.


1. Understanding Indexes in MongoDB

What are Indexes?

An index is a data structure that enhances data retrieval speed by allowing faster access to documents in a collection. Without an index, MongoDB must perform a collection scan, which can be slow for large datasets.

Types of Indexes

  • Unique Indexes: Ensure all values in the indexed field are unique. Ideal for fields like usernames or emails. Typically has a search complexity of O(log n) where n is the number of entries in the index.
  • Non-Unique Indexes: Allow duplicates, useful for fields like categories or tags that don’t require uniqueness. This too has a search complexity of O(log n) but has to additionally deal with duplicates. So the initial lookup time remains the same, but since there could be more than one record with the same index, it still has to traverse the entire B-tree.
          
copy
// 📋 Creating a Unique Index on the "email" Field db.users.createIndex({ email: 1 }, { unique: true }); // 📋 Creating a Non-Unique Index on the "tags" Field db.articles.createIndex({ tags: 1 });

2. How Many Indexes Should You Use?

MongoDB allows up to 64 indexes per collection, but using too many can slow down write operations and increase storage costs. MongoDB recommends a maximum of 15 indexes, though 5-10 is a good range to start with.

💡 Pro Tip: Focus on indexing fields that are frequently queried or where faster access can significantly improve performance.

3. Sparse and Partial Indexes

  • Sparse Indexes: Only include documents with the indexed field. Ideal for fields that may not be present in every document.
          
copy
// 📋 Creating a Sparse Index on the "phone" Field db.customers.createIndex({ phone: 1 }, { sparse: true });
  • Example: If some documents lack a “phone” field, a sparse index on “phone” saves space by only indexing documents that contain it.

  • Partial Indexes: Apply to documents meeting certain conditions, making them more efficient for selective queries.

          
copy
// 📋 Creating a Partial Index for Products with Status "available" db.products.createIndex({ status: 1 }, { partialFilterExpression: { status: "available" } });
  • Example: For an e-commerce site, a partial index on status: "available" improves the efficiency of queries that fetch available products.

Benefits: Both sparse and partial indexes save space and boost performance by indexing only the necessary documents.

4. Full-Text Search Indexes

  • What is Full-Text Search?
    Full-text search indexes allow efficient querying of text fields, such as blog posts or product descriptions.

  • How to Use Full-Text Indexes
    MongoDB’s text index type enables full-text search on one or more fields.

          
copy
// 📋 Creating a Text Index on the "name" Field for Full-Text Search db.articles.createIndex({ name: "text" }); // 📋 Using the Text Index to Find Users Containing the Word "Rohit" in the name db.articles.find({ $text: { $search: "Rohit" } });
  • Example: Creating a text index on the “name” field allows you to search the collection using $text operators, such as finding documents containing the word “Rohit.”

Benefits: Full-text indexes are optimised for text searches and can significantly speed up complex queries in large datasets. But can only search when a full text is entered, for example a record with name - Rohit Nair you would have to search either Rohit or Nair to get this record

💡 Pro Tip: If you absolutely need regex search where Roh should return both usersRohit Nair & Rohan Menon then I would suggest you to match using beginning or end of string instead of full-random search

          
copy
// regex for beginning db.articles.find({ name: { $regex: /^Roh/ } }) // regex for matching ending db.products.find({ name: { $regex: /Nair$/ } }) // optionally pass option i for case insensitive search db.articles.find({ name: { $regex: /^Roh/ }, $options: "i" })

5. Compound Indexes

Compound indexes index multiple fields within a document. They are particularly useful for queries that filter on multiple fields or require sorting.

          
copy
// 📋 Creating a Compound Index on "lastName" and "firstName" Fields db.contacts.createIndex({ lastName: 1, firstName: 1 });
  • How Compound Indexes Work
    Compound indexes store field values in the order specified. This order impacts the index’s effectiveness. For example, an index on { lastName: 1, firstName: 1 } can optimize queries filtering by lastName, or by both lastName and firstName, but not by firstName alone.

  • Use Cases
    Compound indexes are ideal for sorting operations and for queries where you commonly need to filter by more than one field.

          
copy
// 📋 Using a Compound Index to Sort and Filter by Multiple Fields db.contacts.find({ lastName: "Smith" }).sort({ firstName: 1 });

Benefits: Compound indexes can reduce the number of indexes needed and optimize multi-field queries efficiently.

Note: Compound indexes can be both unique or non-unique

6. Best Practices for Using Indexes in MongoDB

  • Start with Key Fields: Begin by indexing the most frequently queried fields.

  • Monitor Performance: Use the explain() method to assess query performance and refine indexes based on query requirements.

          
copy
// 📋 Checking the Performance of a Query with explain() db.users.find({ email: "example@example.com" }).explain("executionStats");
  • Balance Read/Write Performance: Indexes improve read speed but may slow down writes. Find a balance that matches your application’s needs.

  • Use Compound Indexes for Multi-Field Queries: Compound indexes optimize multi-field queries, but they should align with your most common query patterns.

          
copy
// 📋 Example of Creating a Compound Index db.orders.createIndex({ customerId: 1, orderDate: -1 });
  • Target Specific Use Cases: Full-text, sparse, and partial indexes are useful for particular query types, so use them strategically to optimize relevant operations.
  • Checkout MTools: MTools is a collection of scripts to set up MongoDB test environments and parse and visualize MongoDB log files written in python and can be installed via pip, here’s a link to MTools GitHub - MTools GitHub

By effectively using indexes, you can dramatically improve the performance of your MongoDB queries. With these tips and examples, you’ll be able to leverage indexes to enhance responsiveness and scalability as your database grows with your application.

Happy coding! 🧑‍💻