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] }
        }
    }
])

🧠 Test Your Knowledge

Which operator calculates the average of values?