Indexes in MongoDB can dramatically improve the performance of your queries—if used right. In this article, we'll walk through a practical example of how indexes affect query performance, using a simple book database.
We'll go from inserting mock data to analyzing query execution plans, adding indexes, and understanding index limitations.
1. Generate Sample Data
Let's start by populating a collection with mock book data:
// Choose the database
use mylibrary;
// Define helper functions (basic randomizer)
function getRandomElement(arr) {
  return arr[Math.floor(Math.random() * arr.length)];
}
function getRandomInt(min, max) {
  return Math.floor(Math.random() * (max - min + 1)) + min;
}
var genres = ['Fiction', 'Non-Fiction', 'Science', 'Fantasy', 'Biography', 'History', 'Mystery', 'Romance'];
var formats = ['epub', 'pdf', 'txt', 'audio'];
var firstNames = ['John', 'Mary', 'Alice', 'Robert', 'Linda', 'Michael', 'Sarah', 'David'];
var lastNames = ['Smith', 'Johnson', 'Williams', 'Brown', 'Jones', 'Miller', 'Davis', 'Garcia'];
for (var i = 0; i < 1000; i++) {
  var author = getRandomElement(firstNames) + " " + getRandomElement(lastNames);
  var title = "Book Title " + (i + 1);
  var book = {
    author: author,
    title: "title,"
    genre: getRandomElement(genres),
    format: getRandomElement(formats),
    num_of_pages: getRandomInt(50, 1000),
    year_when_published: getRandomInt(1900, 2025)
  };
  db.books.insertOne(book);
}
2. Check Query Execution Without Index
Let’s look at the query plan for a simple .find() operation:
db.books.find().explain("executionStats")
{
  queryPlanner: {
    plannerVersion: 1,
    namespace: 'mylibrary;.books',
    winningPlan: { stage: 'COLLSCAN' }
  },
  executionStats: {
    executionSuccess: true,
    executionTimeMillis: '0.794',
    planningTimeMillis: '0.079',
    executionStages: {
      stage: 'COLLSCAN',
      nReturned: '1915',
      executionTimeMillisEstimate: '0.614'
    }
  },
  ...
}
This uses a COLLSCAN (collection scan), which means MongoDB is scanning every document—inefficient for large datasets.
  
  
  3. Create an Index on the author Field
Let’s improve performance by indexing the author field:
db.books.createIndex({ author: 1 })
4. List All Indexes
db.books.getIndexes()
[
  { v: 4, key: { _id: 1 }, name: '_id_', ns: 'mylibrary;.books' },
  {
    v: 4,
    key: { author: 1 },
    name: 'author_1',
    ns: 'mylibrary;.books'
  }
]
5. Query by Author
db.books.find({ author: "John Smith" }).limit(5).pretty()
6. Query Plan for Author Search
db.books.find({ author: "John Smith" }).explain("executionStats")
{
  queryPlanner: {
    ...
    winningPlan: { stage: 'IXSCAN', indexName: 'author_1', direction: 'forward' }
  },
  executionStats: {
    executionSuccess: true,
    executionTimeMillis: '0.293',
    ...
  }
}
✅ The query now uses an IXSCAN (index scan) which is much faster!
7. Query by Title (No Index)
db.books.find({ title: "Book Title 10" }).explain("executionStats")
{
  queryPlanner: {
    ...
    winningPlan: { stage: 'COLLSCAN' }
  },
  executionStats: {
    executionSuccess: true,
    executionTimeMillis: '1.775',
    ...
  }
}
Still doing a full collection scan—not ideal.
8. Query by Author + Title
db.books.find({ author: "John Smith", title: "Book Title 10" }).explain("executionStats")
{
  queryPlanner: {
    ...
    winningPlan: { stage: 'IXSCAN', indexName: 'author_1', direction: 'forward' }
  },
  ...
}
This is better than a full scan, but still not ideal if you're frequently querying by title.
  
  
  9. Compound Index on year_when_published and title
db.books.createIndex({ year_when_published: 1, title: 1 })
db.books.getIndexes()
[
  ...
  {
    v: 4,
    key: { year_when_published: 1, title: 1 },
    name: 'year_when_published_1_title_1',
    ns: 'mylibrary;.books'
  }
]
Query plan now improves:
db.books.find({ title: "Book Title 10" }).explain("executionStats")
{
  queryPlanner: {
    ...
    winningPlan: {
      stage: 'IXSCAN',
      indexName: 'year_when_published_1_title_1',
      ...
    }
  },
  ...
}
10. Index Size Limitations
Let's test MongoDB's index size limit by trying to insert a document with a huge title:
var longTitle = "A".repeat(5000); // 5000-character string
db.books.insertOne({
  title: longTitle,
  author: "Test Author",
  year_when_published: 2020,
  genre: "Fiction",
  format: "pdf",
  num_of_pages: 300
});
Error:
MongoServerError: key too large to index. Index name: year_when_published_1_title_1
🚫 MongoDB’s index key size is limited (1024 bytes). Long strings in indexed fields can break inserts if the index becomes too large.
🔚 Conclusion
- Indexes can drastically improve query performance.
 - Use 
.explain("executionStats")to analyze and optimize. - Compound indexes are powerful, but mindful of their field sizes.
 - Avoid indexing large strings unless absolutely necessary.
 
    
Top comments (0)