After this lesson, you will be able to: Create single-field, compound, text indexes; use explain() to verify queries hit indexes.
Same B-tree idea as SQL indexes; same write-cost trade-off. The Mongo flavor adds compound key direction + text indexes + geospatial.
Mongo always indexes _id. You add the rest.
// Single-fielddb.users.createIndex({ email: 1 }, { unique: true }); // 1 = asc, -1 = desc// Compounddb.users.createIndex({ age: 1, lastLoginAt: -1 });// Partial (only indexes matching docs, smaller, faster)db.users.createIndex({ email: 1 },{ partialFilterExpression: { active: true } });// TTL, auto-delete after a time (great for sessions / OTP codes)db.sessions.createIndex({ createdAt: 1 }, { expireAfterSeconds: 3600 });// List indexesdb.users.getIndexes();// Dropdb.users.dropIndex({ email: 1 });
explain('executionStats').
// Key fields in output:// winningPlan.stage === "IXSCAN" → index used// winningPlan.stage === "COLLSCAN" → collection scan (bad)// executionStats.executionTimeMillis// executionStats.totalKeysExamined / totalDocsExamined / nReturned//// Ideal ratio: totalKeysExamined ≈ nReturned (low fanout)
Direction matters for sorts.
// Index: { age: 1, joinedAt: -1 }// Uses index:db.users.find({}).sort({ age: 1, joinedAt: -1 });db.users.find({}).sort({ age: -1, joinedAt: 1 }); // exact reversedb.users.find({ age: 30 }).sort({ joinedAt: -1 });// Does NOT use index for sort:db.users.find({}).sort({ age: 1, joinedAt: 1 }); // direction mismatchdb.users.find({}).sort({ joinedAt: -1 }); // skips prefix (age)// Same leftmost-prefix rule as SQL, but ALSO direction must match (or be exact reverse).
Forgetting unique constraint on email (duplicate users). Indexing every field (writes slow, RAM bloats). Compound index in wrong direction for sort (only ASC + DESC reverse work). Skipping explain(), you don't know if your index is used until you check.
Sign in and purchase access to unlock this lesson.