MongoDB Aggregation Operators
Transform and compute data with aggregation expressions
🧮 What are Aggregation Operators?
Aggregation operators perform calculations, transformations, and data manipulations within aggregation pipelines. They help you compute sums, averages, concatenate strings, format dates, and much more.
// Calculate average price
{ $avg: "$price" }
Arithmetic Operators
Arithmetic operators perform mathematical calculations on numeric values. Use them to add, subtract, multiply, divide, and perform other math operations.
$add
Adds numbers together
{ $add: ["$price", "$tax"] }
$subtract
Subtracts one number from another
{ $subtract: ["$price", "$discount"] }
$multiply
Multiplies numbers
{ $multiply: ["$price", "$quantity"] }
$divide
Divides one number by another
{ $divide: ["$total", "$count"] }
🔹 Arithmetic Examples
Use arithmetic operators to calculate new values from existing fields.
🔸 Calculate Total Price
db.orders.aggregate([
{
$project: {
item: 1,
totalPrice: {
$multiply: ["$price", "$quantity"]
}
}
}
])
Input:
{ "_id": 1, "item": "Laptop", "price": 1000, "quantity": 2 }
Output:
{ "_id": 1, "item": "Laptop", "totalPrice": 2000 }
🔸 Calculate Discount Price
db.products.aggregate([
{
$project: {
name: 1,
originalPrice: "$price",
discountedPrice: {
$subtract: [
"$price",
{ $multiply: ["$price", { $divide: ["$discountPercent", 100] }] }
]
}
}
}
])
Input:
{ "_id": 1, "name": "Phone", "price": 500, "discountPercent": 20 }
Output:
{ "_id": 1, "name": "Phone", "originalPrice": 500, "discountedPrice": 400 }
🔹 String Operators
String operators manipulate and transform text values. Concatenate strings, convert case, extract substrings, and more.
🔸 $concat Operator
// Combine first and last name
db.users.aggregate([
{
$project: {
fullName: {
$concat: ["$firstName", " ", "$lastName"]
}
}
}
])
Input:
{ "_id": 1, "firstName": "John", "lastName": "Doe" }
Output:
{ "_id": 1, "fullName": "John Doe" }
🔸 $toUpper and $toLower
// Convert to uppercase
db.products.aggregate([
{
$project: {
name: 1,
upperName: { $toUpper: "$name" },
lowerName: { $toLower: "$name" }
}
}
])
🔸 $substr Operator
// Extract first 3 characters
db.products.aggregate([
{
$project: {
code: { $substr: ["$productCode", 0, 3] }
}
}
])
🔹 Comparison Operators
Comparison operators compare values and return boolean results. Use them in conditional expressions within aggregation pipelines.
🔸 $cmp, $eq, $gt, $lt
// Compare values
db.products.aggregate([
{
$project: {
name: 1,
price: 1,
isExpensive: { $gt: ["$price", 100] },
isCheap: { $lt: ["$price", 50] },
isEqual: { $eq: ["$price", 75] }
}
}
])
Input:
{ "_id": 1, "name": "Widget", "price": 120 }
Output:
{ "_id": 1, "name": "Widget", "price": 120, "isExpensive": true, "isCheap": false, "isEqual": false }
🔹 Conditional Operators
Conditional operators evaluate conditions and return different values based on the result. Perfect for if-then-else logic.
🔸 $cond Operator
// Categorize products by price
db.products.aggregate([
{
$project: {
name: 1,
price: 1,
category: {
$cond: {
if: { $gte: ["$price", 100] },
then: "Premium",
else: "Standard"
}
}
}
}
])
Input:
{ "_id": 1, "name": "Laptop", "price": 1200 }
{ "_id": 2, "name": "Mouse", "price": 25 }
Output:
{ "_id": 1, "name": "Laptop", "price": 1200, "category": "Premium" }
{ "_id": 2, "name": "Mouse", "price": 25, "category": "Standard" }
🔸 $switch Operator
// Multiple conditions
db.orders.aggregate([
{
$project: {
orderNumber: 1,
status: 1,
statusLabel: {
$switch: {
branches: [
{ case: { $eq: ["$status", 1] }, then: "Pending" },
{ case: { $eq: ["$status", 2] }, then: "Processing" },
{ case: { $eq: ["$status", 3] }, then: "Shipped" }
],
default: "Unknown"
}
}
}
}
])
🔹 Array Operators
Array operators work with array fields, allowing you to get array size, filter elements, or check if values exist.
🔸 $size Operator
// Count array elements
db.users.aggregate([
{
$project: {
name: 1,
hobbyCount: { $size: "$hobbies" }
}
}
])
Input:
{ "_id": 1, "name": "John", "hobbies": ["reading", "gaming", "cooking"] }
Output:
{ "_id": 1, "name": "John", "hobbyCount": 3 }
🔸 $in Operator
// Check if value exists in array
db.products.aggregate([
{
$project: {
name: 1,
hasElectronicsTag: {
$in: ["electronics", "$tags"]
}
}
}
])
🔸 $filter Operator
// Filter array elements
db.orders.aggregate([
{
$project: {
orderNumber: 1,
expensiveItems: {
$filter: {
input: "$items",
as: "item",
cond: { $gt: ["$$item.price", 100] }
}
}
}
}
])
🔹 Date Operators
Date operators extract parts of dates or perform date calculations.
🔸 Extract Date Parts
// Get year, month, day from date
db.orders.aggregate([
{
$project: {
orderDate: 1,
year: { $year: "$orderDate" },
month: { $month: "$orderDate" },
day: { $dayOfMonth: "$orderDate" },
dayOfWeek: { $dayOfWeek: "$orderDate" }
}
}
])
Input:
{ "_id": 1, "orderDate": ISODate("2024-03-15") }
Output:
{ "_id": 1, "orderDate": ISODate("2024-03-15"), "year": 2024, "month": 3, "day": 15, "dayOfWeek": 6 }
🔹 Accumulator Operators
Accumulator operators calculate aggregate values across multiple documents. Used primarily in $group stages.
🔸 Common Accumulators
// Calculate statistics
db.sales.aggregate([
{
$group: {
_id: "$category",
totalSales: { $sum: "$amount" },
avgSale: { $avg: "$amount" },
maxSale: { $max: "$amount" },
minSale: { $min: "$amount" },
count: { $sum: 1 }
}
}
])
Input:
{ "category": "Electronics", "amount": 1200 }
{ "category": "Electronics", "amount": 800 }
{ "category": "Books", "amount": 50 }
Output:
{ "_id": "Electronics", "totalSales": 2000, "avgSale": 1000, "maxSale": 1200, "minSale": 800, "count": 2 }
{ "_id": "Books", "totalSales": 50, "avgSale": 50, "maxSale": 50, "minSale": 50, "count": 1 }
🔹 Practical Examples
Combine operators for complex transformations:
Example 1: Order Summary
db.orders.aggregate([
{
$project: {
orderNumber: 1,
customerName: { $concat: ["$customer.firstName", " ", "$customer.lastName"] },
totalAmount: { $multiply: ["$price", "$quantity"] },
status: {
$cond: {
if: { $eq: ["$shipped", true] },
then: "Delivered",
else: "Pending"
}
},
orderYear: { $year: "$orderDate" }
}
}
])
Example 2: Product Analytics
db.products.aggregate([
{
$project: {
name: 1,
priceCategory: {
$switch: {
branches: [
{ case: { $lt: ["$price", 50] }, then: "Budget" },
{ case: { $lt: ["$price", 200] }, then: "Mid-Range" },
{ case: { $gte: ["$price", 200] }, then: "Premium" }
],
default: "Unknown"
}
},
tagCount: { $size: "$tags" },
inStock: { $gt: ["$stock", 0] }
}
}
])