MongoDB Indexing
40 minIndexes are critical for MongoDB performance, enabling fast data retrieval without scanning entire collections. An index is a data structure that stores a small portion of collection data in an easy-to-traverse form, allowing MongoDB to quickly locate documents matching query criteria. Without indexes, MongoDB must perform collection scans, examining every document, which becomes prohibitively slow as collections grow. Understanding indexing is essential for building performant MongoDB applications.
Single field indexes are the simplest type, created on a single field. Indexes can be ascending (1) or descending (-1), which matters primarily for compound indexes and sort operations. Single field indexes are ideal for queries filtering or sorting by a single field. MongoDB automatically creates an index on the _id field for all collections. Understanding single field indexes enables basic query optimization.
Compound indexes are created on multiple fields and support queries that filter or sort by those fields. The order of fields in a compound index matters: MongoDB can use a compound index for queries on the prefix of the indexed fields. For example, an index on { city: 1, age: -1 } can be used for queries on city alone, or city and age together, but not age alone. Understanding compound index field order enables optimal index design.
Multikey indexes are automatically created when you index array fields. MongoDB creates an index entry for each element in the array, enabling efficient queries on array contents. Multikey indexes support queries that match any element in an array. However, compound indexes can have at most one array field. Understanding multikey indexes enables efficient querying of array data.
Text indexes enable full-text search on string content. Text indexes tokenize and stem text, enabling searches for words and phrases. Only one text index can exist per collection, but it can index multiple fields. Text search uses $text operator and supports language-specific stemming. Understanding text indexes enables implementing search functionality in MongoDB applications.
Geospatial indexes support location-based queries. 2dsphere indexes support queries on GeoJSON objects and legacy coordinate pairs, enabling queries like finding points within a radius or within a polygon. Geospatial indexes are essential for location-based applications. Understanding geospatial indexes enables building mapping and location services. Best practices include creating indexes on frequently queried fields, monitoring index usage, and removing unused indexes to reduce write overhead.
Key Concepts
- Indexes improve query performance by providing fast data access.
- Single field indexes are created on individual fields.
- Compound indexes support queries on multiple fields.
- Multikey indexes automatically index array elements.
- Text and geospatial indexes support specialized queries.
Learning Objectives
Master
- Creating single field and compound indexes
- Understanding index types and their use cases
- Using indexes to optimize query performance
- Managing indexes effectively
Develop
- Understanding database indexing principles
- Designing optimal index strategies
- Balancing query performance with write performance
Tips
- Create indexes on frequently queried fields: db.collection.createIndex({ field: 1 }).
- Use compound indexes for multi-field queries: db.collection.createIndex({ field1: 1, field2: -1 }).
- Check index usage: db.collection.getIndexes() to see all indexes.
- Use explain() to see if indexes are used: db.collection.find({}).explain('executionStats').
Common Pitfalls
- Creating too many indexes, slowing down write operations.
- Not creating indexes on queried fields, causing slow queries.
- Not understanding compound index field order, creating inefficient indexes.
- Not monitoring index usage, maintaining unused indexes.
Summary
- Indexes are essential for MongoDB query performance.
- Different index types serve different query patterns.
- Understanding index types enables optimal performance.
- Balancing indexes with write performance is important.
Exercise
Create and manage different types of indexes.
// Sample data for indexing
db.users.insertMany([
{ name: "Alice", email: "alice@example.com", age: 25, city: "New York", createdAt: new Date() },
{ name: "Bob", email: "bob@example.com", age: 30, city: "Los Angeles", createdAt: new Date() },
{ name: "Carol", email: "carol@example.com", age: 35, city: "Chicago", createdAt: new Date() },
{ name: "David", email: "david@example.com", age: 28, city: "New York", createdAt: new Date() },
{ name: "Eve", email: "eve@example.com", age: 32, city: "Boston", createdAt: new Date() }
])
// Single field index
db.users.createIndex({ email: 1 })
// Compound index
db.users.createIndex({ city: 1, age: -1 })
// Unique index
db.users.createIndex({ email: 1 }, { unique: true })
// Sparse index (only on documents that have the field)
db.users.createIndex({ phone: 1 }, { sparse: true })
// Text index for full-text search
db.users.createIndex({ name: "text", email: "text" })
// Geospatial index
db.users.createIndex({ location: "2dsphere" })
// TTL index (Time To Live)
db.sessions.createIndex({ createdAt: 1 }, { expireAfterSeconds: 3600 })
// Partial index (only on documents matching a filter)
db.users.createIndex(
{ age: 1 },
{ partialFilterExpression: { age: { $gte: 18 } }}
)
// View existing indexes
db.users.getIndexes()
// Analyze query performance
db.users.find({ email: "alice@example.com" }).explain("executionStats")
// Drop an index
db.users.dropIndex("email_1")
// Drop all indexes (except _id)
db.users.dropIndexes()
Exercise Tips
- Use unique indexes for constraints: db.collection.createIndex({ field: 1 }, { unique: true }).
- Use sparse indexes for optional fields: db.collection.createIndex({ field: 1 }, { sparse: true }).
- Use TTL indexes for automatic expiration: db.collection.createIndex({ date: 1 }, { expireAfterSeconds: 3600 }).
- Monitor index size: db.collection.stats().indexSizes to see index storage usage.