Aggregation & Indexes Aggregation Pipeline Stages are processed in order, each stage's output is the next stage's input. const pipeline = [ // $match — filter (…
Aggregation & Indexes
Aggregation Pipeline
Stages are processed in order, each stage's output is the next stage's input.
const pipeline = [
// $match — filter (like WHERE, use early to limit docs)
{ $match: { active: true, age: { $gte: 18 } } },
// $group — group and aggregate (like GROUP BY)
{
$group: {
_id: '$country',
count: { $sum: 1 },
avgAge: { $avg: '$age' },
emails: { $push: '$email' },
minAge: { $min: '$age' },
maxAge: { $max: '$age' },
}
},
// $sort — sort results
{ $sort: { count: -1 } },
// $limit and $skip — pagination
{ $skip: 0 },
{ $limit: 10 },
// $project — reshape documents
{
$project: {
country: '$_id',
count: 1,
avgAge: { $round: ['$avgAge', 1] },
_id: 0,
}
},
];
const results = await users.aggregate(pipeline).toArray();
// $lookup — JOIN another collection
const ordersWithUsers = await orders.aggregate([
{
$lookup: {
from: 'users',
localField: 'userId',
foreignField: '_id',
as: 'user',
}
},
{ $unwind: '$user' }, // flatten array to single doc
{ $project: { total: 1, 'user.name': 1, 'user.email': 1 } },
]).toArray();
// $unwind — flatten array field
await posts.aggregate([
{ $unwind: '$tags' }, // one doc per tag
{ $group: { _id: '$tags', count: { $sum: 1 } } },
{ $sort: { count: -1 } },
]).toArray();
// $addFields / $set
await users.aggregate([
{ $addFields: { fullName: { $concat: ['$firstName', ' ', '$lastName'] } } },
]).toArray();
// $facet — multiple pipelines in one pass
await products.aggregate([
{
$facet: {
totalCount: [{ $count: 'count' }],
byCategory: [{ $group: { _id: '$category', count: { $sum: 1 } } }],
priceStats: [{ $group: { _id: null, avg: { $avg: '$price' }, min: { $min: '$price' } } }],
}
}
]).toArray();
Indexes
// Single field
await users.createIndex({ email: 1 }); // ascending
await users.createIndex({ createdAt: -1 }); // descending (for latest first)
// Unique index
await users.createIndex({ email: 1 }, { unique: true });
// Compound index (order matters — use ESR rule: Equality, Sort, Range)
await users.createIndex({ country: 1, createdAt: -1 });
// Partial index — index only matching documents
await users.createIndex(
{ email: 1 },
{ partialFilterExpression: { active: true } }
);
// Sparse index — skip documents where field doesn't exist
await users.createIndex({ phone: 1 }, { sparse: true });
// TTL index — auto-delete documents after N seconds
await sessions.createIndex({ createdAt: 1 }, { expireAfterSeconds: 86400 }); // 24h
// Text index for full-text search
await articles.createIndex({ title: 'text', body: 'text' });
await articles.find({ $text: { $search: 'mongodb performance' } }).toArray();
// Wildcard index
await products.createIndex({ 'attributes.$**': 1 });
// List indexes
await users.listIndexes().toArray();
// Drop index
await users.dropIndex({ email: 1 });
// Explain
await users.find({ email: 'a@b.com' }).explain('executionStats');
Mongoose (ODM)
import mongoose, { Schema, model, Document } from 'mongoose';
// Schema definition
const userSchema = new Schema({
email: { type: String, required: true, unique: true, lowercase: true, trim: true },
name: { type: String, required: true, minlength: 2 },
age: { type: Number, min: 0, max: 150 },
roles: [{ type: String, enum: ['user', 'admin', 'mod'] }],
address: {
city: String,
country: { type: String, default: 'US' },
},
}, {
timestamps: true, // adds createdAt, updatedAt
toJSON: { virtuals: true },
});
// Virtual field
userSchema.virtual('isAdult').get(function() {
return this.age >= 18;
});
// Methods
userSchema.methods.greet = function() {
return `Hello, ${this.name}`;
};
// Statics
userSchema.statics.findByEmail = function(email: string) {
return this.findOne({ email: email.toLowerCase() });
};
// Pre-save hook
userSchema.pre('save', async function(next) {
if (this.isModified('password')) {
this.password = await bcrypt.hash(this.password, 10);
}
next();
});
const User = model('User', userSchema);
// CRUD with Mongoose
const user = await User.create({ email: 'a@b.com', name: 'Alice' });
const users = await User.find({ active: true }).select('name email').lean();
await User.findByIdAndUpdate(id, { $inc: { loginCount: 1 } }, { new: true });
await User.findByIdAndDelete(id);