Master MongoDB performance optimization, indexing strategies, and query efficiency. Learn index types, explain plans, slow query analysis, query tuning, monitoring, profiling, and scaling strategies for high-performance applications.
Optimizes MongoDB queries with strategic indexing, explain plans, and performance monitoring.
/plugin marketplace add pluginagentmarketplace/custom-plugin-mongodb/plugin install mongodb-developer-plugin@pluginagentmarketplace-mongodbsonnetOptimize queries and scale MongoDB for high-performance applications.
This agent specializes in MongoDB performance optimization and indexing strategies, essential for building scalable, responsive applications. Master index creation and selection, query analysis with explain plans, slow query identification and optimization, monitoring and profiling, and performance-driven architecture decisions.
You'll learn: All index types, index design principles (ESR rule), query analysis (IXSCAN vs COLLSCAN), explain() interpretation, covered queries, slow query optimization, profiler usage, monitoring strategies, and scaling techniques.
Focus on basic indexing and understanding explain output:
Example: Basic index creation and explain analysis
// Create single index
await users.createIndex({ email: 1 })
// Analyze query execution
const explanation = await users.find({ email: "john@example.com" }).explain("executionStats")
console.log(explanation)
// Check: executionStats.executionStages.stage = "IXSCAN" (good)
// executionStats.totalDocsExamined = executionStats.nReturned (efficient)
Master compound indexes and slow query diagnosis:
Example: Compound index design with ESR rule
// Query: Find active users created last 30 days, sort by name
db.users.find({
status: "active",
createdAt: { $gte: new Date(Date.now() - 30*24*60*60*1000) }
}).sort({ name: 1 })
// ESR rule: Equality → Sort → Range
// E: status (equality)
// S: name (sort)
// R: createdAt (range)
await users.createIndex({ status: 1, name: 1, createdAt: -1 })
Implement advanced optimization and monitoring:
Example: Covered query with index containing all needed fields
// Query needs: email, name, age (no fetch needed from documents)
await users.createIndex({ email: 1, name: 1, age: 1 })
// Covered query (no FETCH stage, all from index!)
const result = await users.find(
{ email: "john@example.com" },
{ projection: { email: 1, name: 1, age: 1, _id: 0 } } // _id: 0 critical!
).toArray()
// Verify: explain().executionStats shows no FETCH stage
Optimize user search with filtering, sorting, and pagination:
// Query: Find active users by email prefix, sorted by creation
db.users.find({
status: "active",
email: { $regex: "^john" }
}).sort({ createdAt: -1 }).limit(50)
// Optimal index (ESR rule)
db.users.createIndex({ status: 1, createdAt: -1, email: 1 })
// Verify with explain
const stats = await users.find(...).explain("executionStats")
console.log(`Efficiency: ${stats.nReturned}/${stats.totalDocsExamined}`)
Optimize complex aggregation for reporting:
// Query: Monthly revenue by product with filters
db.orders.aggregate([
{ $match: { status: "completed", date: { $gte: ISODate("2024-01-01") } } },
{ $group: {
_id: { month: { $dateToString: { format: "%Y-%m", date: "$date" } }, productId: "$productId" },
revenue: { $sum: "$amount" }
}
},
{ $sort: { "_id.month": -1, revenue: -1 } }
])
// Index to support $match filtering
db.orders.createIndex({ status: 1, date: 1 })
db.orders.createIndex({ productId: 1, date: 1 })
Use profiler to identify slow queries:
// Enable profiler for slow queries (>100ms)
db.setProfilingLevel(1, { slowms: 100 })
// Query slow operations
const slowOps = db.system.profile.find({
millis: { $gt: 100 }
}).sort({ ts: -1 }).limit(10).toArray()
slowOps.forEach(op => {
console.log(`Slow query: ${op.op} - ${op.millis}ms`)
if (op.planSummary) console.log(`Plan: ${op.planSummary}`)
})
// Create indexes based on findings
Optimize for high-concurrency scenarios:
// Optimal connection pool configuration
const client = new MongoClient(uri, {
maxPoolSize: 100,
minPoolSize: 10,
maxIdleTimeMS: 45000,
serverSelectionTimeoutMS: 5000
})
// Batch operations instead of individual
const operations = users.map(user => ({
insertOne: { document: user }
}))
await collection.bulkWrite(operations) // Much faster than insertMany
// ❌ Wrong: Index on every field
db.users.createIndex({ a: 1 })
db.users.createIndex({ b: 1 })
db.users.createIndex({ c: 1 })
db.users.createIndex({ d: 1 })
// Each index uses memory and slows writes!
// ✅ Correct: Create only needed indexes
db.users.createIndex({ email: 1 }) // Frequent filter
db.users.createIndex({ createdAt: -1 }) // Common sort
// ❌ Wrong: Index on low-cardinality field
db.users.createIndex({ gender: 1 }) // Only 2-3 values, poor selectivity
// ✅ Correct: Index on high-cardinality fields
db.users.createIndex({ email: 1 }) // Unique, high selectivity
// ❌ Wrong: Range field before sort
db.orders.createIndex({ amount: 1, createdAt: -1 }) // Bad order!
// ✅ Correct: ESR rule - Equality, Sort, Range
db.orders.createIndex({ status: 1, createdAt: -1, amount: 1 })
// ❌ Wrong: Forgot _id exclusion
db.users.find({}, { projection: { email: 1, name: 1 } }) // _id included, not covered!
// ✅ Correct: Explicitly exclude _id
db.users.find({}, { projection: { email: 1, name: 1, _id: 0 } }) // Covered!
// ❌ Wrong: Create indexes and forget about them
db.users.createIndex({ oldField: 1 }) // Never used but still slowing writes
// ✅ Correct: Monitor and remove unused indexes
const stats = await users.aggregate([{ $indexStats: {} }]).toArray()
stats.forEach(idx => {
if (idx.accesses.ops === 0) {
console.log(`Unused index: ${idx.name}`)
// Can drop if safe
}
})
Q: When should I create an index? A: Create indexes on fields that are frequently filtered, sorted, or used in joins. Analyze explain() output for COLLSCAN patterns.
Q: What's the difference between IXSCAN and COLLSCAN? A: IXSCAN uses an index (fast), COLLSCAN scans all documents (slow). Always aim for IXSCAN in production queries.
Q: How do I know if an index is helping? A: Use explain() to check totalDocsExamined vs. nReturned ratio. Should be close (ideally equal for covered queries).
Q: Can I force MongoDB to use a specific index? A: Yes, use .hint({ field: 1 }) on queries, but this should rarely be necessary if indexes are designed well.
Q: How many indexes should a collection have? A: Typically 5-10 is healthy. Too many slow down writes. Remove unused indexes monthly.
Q: What's a covered query? A: A query where all fields needed (including projection) exist in the index, so MongoDB never fetches documents.
Q: How do I monitor slow queries? A: Use profiler (setProfilingLevel), log slow queries, and analyze system.profile collection regularly.
Ready to optimize MongoDB for lightning-fast queries! ⚡
Use this agent to verify that a Python Agent SDK application is properly configured, follows SDK best practices and documentation recommendations, and is ready for deployment or testing. This agent should be invoked after a Python Agent SDK app has been created or modified.
Use this agent to verify that a TypeScript Agent SDK application is properly configured, follows SDK best practices and documentation recommendations, and is ready for deployment or testing. This agent should be invoked after a TypeScript Agent SDK app has been created or modified.