Skip to main content

MongoDB Aggregation

Basic Aggregation Pipeline

// Simple pipeline structure
db.collection.aggregate([
{ $stage1: {...} },
{ $stage2: {...} },
{ $stage3: {...} }
]);

Common Pipeline Stages

$match - Filter Documents

// Filter at the beginning
db.orders.aggregate([
{ $match: { status: "completed", total: { $gte: 100 } } }
]);

// Filter after transformation
db.orders.aggregate([
{ $addFields: { year: { $year: "$createdAt" } } },
{ $match: { year: 2024 } }
]);

$group - Group and Aggregate

// Count by category
db.products.aggregate([
{ $group: { _id: "$category", count: { $sum: 1 } } }
]);

// Sum and average
db.orders.aggregate([
{
$group: {
_id: "$customerId",
totalSpent: { $sum: "$amount" },
avgOrder: { $avg: "$amount" },
orderCount: { $sum: 1 }
}
}
]);

// Min, max, first, last
db.sales.aggregate([
{
$group: {
_id: "$product",
minPrice: { $min: "$price" },
maxPrice: { $max: "$price" },
firstSale: { $first: "$date" },
lastSale: { $last: "$date" }
}
}
]);

// Collect values into array
db.orders.aggregate([
{
$group: {
_id: "$customerId",
orderIds: { $push: "$_id" },
uniqueProducts: { $addToSet: "$productId" }
}
}
]);

$project - Reshape Documents

// Select and rename fields
db.users.aggregate([
{
$project: {
fullName: "$name",
email: 1,
age: "$profile.age",
_id: 0
}
}
]);

// Computed fields
db.orders.aggregate([
{
$project: {
orderId: 1,
total: 1,
tax: { $multiply: ["$total", 0.08] },
grandTotal: { $add: ["$total", { $multiply: ["$total", 0.08] }] }
}
}
]);

// Conditional fields
db.users.aggregate([
{
$project: {
name: 1,
ageGroup: {
$cond: {
if: { $gte: ["$age", 18] },
then: "adult",
else: "minor"
}
}
}
}
]);

$sort - Sort Documents

// Sort by single field
db.products.aggregate([
{ $sort: { price: -1 } }
]);

// Sort by multiple fields
db.orders.aggregate([
{ $sort: { status: 1, createdAt: -1 } }
]);

$limit and $skip - Pagination

// Limit results
db.products.aggregate([
{ $sort: { price: -1 } },
{ $limit: 10 }
]);

// Skip and limit (pagination)
db.products.aggregate([
{ $sort: { createdAt: -1 } },
{ $skip: 20 },
{ $limit: 10 }
]);

$unwind - Deconstruct Arrays

// Unwind array field
db.orders.aggregate([
{ $unwind: "$items" }
]);

// Unwind with options
db.orders.aggregate([
{
$unwind: {
path: "$items",
includeArrayIndex: "itemIndex",
preserveNullAndEmptyArrays: true
}
}
]);

$lookup - Join Collections

// Basic lookup
db.orders.aggregate([
{
$lookup: {
from: "customers",
localField: "customerId",
foreignField: "_id",
as: "customer"
}
}
]);

// Advanced lookup with pipeline
db.orders.aggregate([
{
$lookup: {
from: "products",
let: { orderItems: "$items" },
pipeline: [
{
$match: {
$expr: { $in: ["$_id", "$$orderItems.productId"] }
}
},
{ $project: { name: 1, price: 1 } }
],
as: "productDetails"
}
}
]);

$addFields - Add/Update Fields

// Add computed fields
db.orders.aggregate([
{
$addFields: {
year: { $year: "$createdAt" },
itemCount: { $size: "$items" },
hasDiscount: { $gt: ["$discount", 0] }
}
}
]);

Complex Aggregation Examples

Sales Analytics

db.orders.aggregate([
// Filter completed orders from this year
{
$match: {
status: "completed",
createdAt: { $gte: new Date("2024-01-01") }
}
},
// Add computed fields
{
$addFields: {
month: { $month: "$createdAt" },
year: { $year: "$createdAt" }
}
},
// Group by month
{
$group: {
_id: { year: "$year", month: "$month" },
totalRevenue: { $sum: "$total" },
orderCount: { $sum: 1 },
avgOrderValue: { $avg: "$total" },
uniqueCustomers: { $addToSet: "$customerId" }
}
},
// Add customer count
{
$addFields: {
customerCount: { $size: "$uniqueCustomers" }
}
},
// Sort by month
{ $sort: { "_id.year": 1, "_id.month": 1 } },
// Shape final output
{
$project: {
month: "$_id.month",
year: "$_id.year",
revenue: "$totalRevenue",
orders: "$orderCount",
avgOrder: { $round: ["$avgOrderValue", 2] },
customers: "$customerCount",
_id: 0
}
}
]);

Top Products by Category

db.products.aggregate([
// Match active products
{ $match: { status: "active" } },
// Group by category
{
$group: {
_id: "$category",
products: {
$push: {
name: "$name",
price: "$price",
rating: "$rating",
sales: "$salesCount"
}
}
}
},
// Sort products within each category
{
$addFields: {
topProducts: {
$slice: [
{
$sortArray: {
input: "$products",
sortBy: { sales: -1 }
}
},
5
]
}
}
},
{
$project: {
category: "$_id",
topProducts: 1,
_id: 0
}
}
]);

Aggregation Operators

Arithmetic

{
total: { $add: ["$price", "$tax"] },
discount: { $subtract: ["$price", "$salePrice"] },
finalPrice: { $multiply: ["$price", 0.9] },
avgRating: { $divide: ["$totalRating", "$ratingCount"] },
remainder: { $mod: ["$quantity", 10] }
}

Array Operations

{
itemCount: { $size: "$items" },
hasItems: { $gt: [{ $size: "$items" }, 0] },
firstItem: { $arrayElemAt: ["$items", 0] },
allTags: { $concatArrays: ["$tags", "$categories"] },
uniqueTags: { $setUnion: ["$tags", []] }
}

String Operations

{
fullName: { $concat: ["$firstName", " ", "$lastName"] },
upperName: { $toUpper: "$name" },
nameLength: { $strLenCP: "$name" },
domain: { $arrayElemAt: [{ $split: ["$email", "@"] }, 1] }
}

Date Operations

{
year: { $year: "$createdAt" },
month: { $month: "$createdAt" },
dayOfWeek: { $dayOfWeek: "$createdAt" },
ageInDays: { $divide: [{ $subtract: [new Date(), "$birthDate"] }, 86400000] }
}