Indexes

Basic Index Operations

Create Index

// Single field index
db.users.createIndex({ email: 1 })

// Compound index
db.users.createIndex({ firstName: 1, lastName: 1 })

// Unique index
db.users.createIndex({ email: 1 }, { unique: true })

// Sparse index
db.users.createIndex({ phone: 1 }, { sparse: true })

// Text index
db.users.createIndex({ name: "text", description: "text" })

// Geospatial index
db.users.createIndex({ location: "2dsphere" })

// TTL index
db.sessions.createIndex({ createdAt: 1 }, { expireAfterSeconds: 3600 })

List Indexes

// Show all indexes
db.users.getIndexes()

// Show index details
db.users.getIndexSpecs()

// Show index stats
db.users.getIndexStats()

Drop Index

// Drop by name
db.users.dropIndex("email_1")

// Drop by specification
db.users.dropIndex({ email: 1 })

// Drop all indexes (except _id)
db.users.dropIndexes()

Index Types

Single Field Index

// Ascending index
db.users.createIndex({ age: 1 })

// Descending index
db.users.createIndex({ createdAt: -1 })

// On nested field
db.users.createIndex({ "profile.firstName": 1 })

// On array field
db.users.createIndex({ tags: 1 })

Compound Index

// Multiple fields
db.users.createIndex({ lastName: 1, firstName: 1 })

// Mixed order
db.users.createIndex({ category: 1, price: -1 })

// With nested fields
db.users.createIndex({ 
    "profile.city": 1, 
    "profile.state": 1 
})

// Compound with array
db.users.createIndex({ 
    category: 1, 
    tags: 1 
})

Unique Index

// Unique single field
db.users.createIndex({ email: 1 }, { unique: true })

// Unique compound
db.users.createIndex({ 
    username: 1, 
    domain: 1 
}, { unique: true })

// Unique sparse
db.users.createIndex({ 
    phone: 1 
}, { 
    unique: true, 
    sparse: true 
})

// Partial unique
db.users.createIndex({ email: 1 }, {
    unique: true,
    partialFilterExpression: { email: { $exists: true } }
})

Sparse Index

// Sparse index (skips null/missing values)
db.users.createIndex({ phone: 1 }, { sparse: true })

// Sparse unique
db.users.createIndex({ email: 1 }, { 
    unique: true, 
    sparse: true 
})

// Sparse compound
db.users.createIndex({ 
    phone: 1, 
    fax: 1 
}, { sparse: true })

Text Index

// Single field text index
db.products.createIndex({ description: "text" })

// Multiple fields text index
db.products.createIndex({ 
    name: "text", 
    description: "text",
    tags: "text"
})

// Text index with weights
db.products.createIndex({ 
    name: "text", 
    description: "text" 
}, {
    weights: {
        name: 10,
        description: 5
    }
})

// Text index with language
db.products.createIndex({ description: "text" }, {
    default_language: "english"
})

Geospatial Index

// 2dsphere index
db.places.createIndex({ location: "2dsphere" })

// 2d index
db.places.createIndex({ location: "2d" })

// GeoHaystack index
db.places.createIndex({ 
    location: "geoHaystack", 
    category: 1 
}, { bucketSize: 1 })

TTL Index

// TTL index with expiration
db.sessions.createIndex({ 
    createdAt: 1 
}, { 
    expireAfterSeconds: 3600 
})

// TTL on specific time
db.logs.createIndex({ 
    timestamp: 1 
}, { 
    expireAfterSeconds: 86400 
})

// TTL with partial filter
db.tempData.createIndex({ 
    createdAt: 1 
}, { 
    expireAfterSeconds: 1800,
    partialFilterExpression: { 
        type: "temporary" 
    }
})

Partial Index

// Partial index with filter
db.users.createIndex({ email: 1 }, {
    partialFilterExpression: { 
        status: "active" 
    }
})

// Partial index with conditions
db.orders.createIndex({ orderDate: 1 }, {
    partialFilterExpression: { 
        amount: { $gt: 100 } 
    }
})

// Partial index with multiple conditions
db.products.createIndex({ price: 1 }, {
    partialFilterExpression: {
        $and: [
            { category: "electronics" },
            { inStock: true }
        ]
    }
})

Wildcard Index

// Wildcard index on all fields
db.users.createIndex({ "$**": 1 })

// Wildcard index on specific path
db.users.createIndex({ "profile.$**": 1 })

// Wildcard index with projection
db.users.createIndex({ "$**": 1 }, {
    wildcardProjection: {
        "profile": 1,
        "metadata": 1,
        "password": 0
    }
})

Index Options

Basic Options

// Background index creation
db.users.createIndex({ email: 1 }, { background: true })

// Index with name
db.users.createIndex({ email: 1 }, { name: "email_index" })

// Index with collation
db.users.createIndex({ name: 1 }, {
    collation: { locale: "en", strength: 2 }
})

// Index with storage engine
db.users.createIndex({ email: 1 }, {
    storageEngine: { wiredTiger: { configString: "block_compressor=zlib" } }
})

Advanced Options

// Index with custom name
db.users.createIndex({ email: 1 }, { 
    name: "user_email_unique_index" 
})

// Index with comment
db.users.createIndex({ email: 1 }, { 
    name: "email_index",
    comment: "Index for email lookups"
})

// Index with hidden option
db.users.createIndex({ email: 1 }, { 
    hidden: true 
})

Index Management

Check Index Usage

// Get index usage stats
db.users.aggregate([
    { $indexStats: {} }
])

// Get index details
db.users.getIndexes()

// Check index size
db.users.stats().indexSizes

Analyze Index Performance

// Explain query with index
db.users.find({ email: "john@example.com" }).explain("executionStats")

// Explain aggregation with index
db.users.aggregate([
    { $match: { age: { $gte: 25 } } }
]).explain("executionStats")

// Check if index is used
db.users.find({ email: "john@example.com" }).explain("queryPlanner")

Index Maintenance

// Rebuild index
db.users.reIndex()

// Validate index
db.users.validate({ full: true })

// Compact collection (reduces index size)
db.runCommand({ compact: "users" })

Index Optimization

Query Optimization

// Covered query (index only)
db.users.find(
    { email: "john@example.com" },
    { _id: 0, email: 1 }
)

// Compound index for range queries
db.users.createIndex({ 
    lastName: 1, 
    firstName: 1, 
    age: 1 
})

// Index for sorting
db.users.createIndex({ 
    category: 1, 
    price: -1 
})

Index Design Patterns

Equality, Sort, Range (ESR)

// Good index design
db.orders.createIndex({ 
    status: 1,        // Equality
    orderDate: -1,    // Sort
    amount: 1         // Range
})

// Query pattern
db.orders.find({
    status: "pending",
    amount: { $gt: 100 }
}).sort({ orderDate: -1 })

Compound Index Order

// Most selective first
db.users.createIndex({ 
    email: 1,         // High selectivity
    status: 1,        // Medium selectivity
    createdAt: 1      // Low selectivity
})

Index for Aggregation

// Index for aggregation pipeline
db.orders.createIndex({ 
    status: 1, 
    orderDate: 1 
})

// Aggregation query
db.orders.aggregate([
    { $match: { status: "completed" } },
    { $group: { 
        _id: { $dateToString: { format: "%Y-%m", date: "$orderDate" } },
        total: { $sum: "$amount" }
    }},
    { $sort: { _id: 1 } }
])

Common Index Patterns

User Management

// User lookup by email
db.users.createIndex({ email: 1 }, { unique: true })

// User search by name
db.users.createIndex({ 
    firstName: 1, 
    lastName: 1 
})

// User by location
db.users.createIndex({ 
    "profile.city": 1, 
    "profile.state": 1 
})

// User by status and date
db.users.createIndex({ 
    status: 1, 
    createdAt: -1 
})

E-commerce

// Product search
db.products.createIndex({ 
    name: "text", 
    description: "text" 
})

// Product by category and price
db.products.createIndex({ 
    category: 1, 
    price: 1 
})

// Product availability
db.products.createIndex({ 
    inStock: 1, 
    category: 1 
})

// Product ratings
db.products.createIndex({ 
    "ratings.average": -1, 
    category: 1 
})

Order Management

// Order by customer
db.orders.createIndex({ customerId: 1 })

// Order by status and date
db.orders.createIndex({ 
    status: 1, 
    orderDate: -1 
})

// Order by amount range
db.orders.createIndex({ 
    amount: 1, 
    orderDate: -1 
})

// Order lookup by number
db.orders.createIndex({ orderNumber: 1 }, { unique: true })

Analytics

// Time series data
db.events.createIndex({ 
    timestamp: -1, 
    eventType: 1 
})

// User activity
db.activities.createIndex({ 
    userId: 1, 
    activityDate: -1 
})

// Metrics aggregation
db.metrics.createIndex({ 
    metricName: 1, 
    timestamp: -1 
})

Index Best Practices

Performance Tips

// Use background indexing for large collections
db.largeCollection.createIndex({ field: 1 }, { background: true })

// Create indexes before data insertion
db.users.createIndex({ email: 1 }, { background: true })

// Monitor index usage
db.users.aggregate([{ $indexStats: {} }])

// Remove unused indexes
db.users.dropIndex("unused_index_name")

Index Limitations

// Maximum index key size: 1024 bytes
// Maximum compound index fields: 32
// Maximum indexes per collection: 64
// Text indexes: only one per collection
// Geospatial indexes: only one per collection

Index Sizing

// Check index size
db.users.stats().indexSizes

// Check total index size
db.users.stats().totalIndexSize

// Check index build progress
db.currentOp({ "createIndexes": { $exists: true } })

Troubleshooting Indexes

Common Issues

// Index too large
db.users.createIndex({ largeField: 1 })  // May fail if > 1024 bytes

// Duplicate key error
db.users.createIndex({ email: 1 }, { unique: true })
// Insert duplicate email will fail

// Sparse index with null values
db.users.createIndex({ phone: 1 }, { sparse: true })
// Documents without phone field won't be indexed

// Text index limitations
db.products.createIndex({ name: "text" })
// Only one text index per collection

Performance Issues

// Slow queries - check if index is used
db.users.find({ email: "john@example.com" }).explain("executionStats")

// Large index scans - add more specific indexes
db.users.createIndex({ status: 1, email: 1 })

// Index not used - check query pattern
// Ensure query matches index order and fields

Last updated