Lesson 45 of 50 – Aggregation Reports Project
90%

MongoDB Aggregation Reports

MongoDB aggregation allows us to process documents, calculate totals, group records, and generate useful reports. In this lesson, we will create sales, product, department, and monthly revenue reports using the aggregation pipeline.

1. Introduction to Aggregation Reports

Suppose we have a sales database with the following collections:

  • sales — sales transaction records
  • products — product details
  • employees — employee information

Example database and collection setup:

use salesDB

db.createCollection("sales")
db.createCollection("products")
db.createCollection("employees")

Common aggregation stages include:

  • $match — filters documents.
  • $group — groups documents and calculates totals.
  • $project — selects or calculates output fields.
  • $sort — sorts the results.
  • $limit — limits the number of results.
  • $lookup — combines matching documents from another collection.
  • $unwind — separates array elements into individual documents.

2. Insert Sample Sales Records

Insert sample sales data into the sales collection:

db.sales.insertMany([
    {
        sale_id: 1001,
        product: "Laptop",
        category: "Electronics",
        quantity: 2,
        price: 50000,
        salesperson: "Rahul",
        sale_date: ISODate("2026-01-10T00:00:00Z")
    },
    {
        sale_id: 1002,
        product: "Mouse",
        category: "Accessories",
        quantity: 5,
        price: 500,
        salesperson: "Priya",
        sale_date: ISODate("2026-01-15T00:00:00Z")
    },
    {
        sale_id: 1003,
        product: "Laptop",
        category: "Electronics",
        quantity: 1,
        price: 50000,
        salesperson: "Rahul",
        sale_date: ISODate("2026-02-05T00:00:00Z")
    },
    {
        sale_id: 1004,
        product: "Keyboard",
        category: "Accessories",
        quantity: 3,
        price: 1500,
        salesperson: "Amit",
        sale_date: ISODate("2026-02-12T00:00:00Z")
    },
    {
        sale_id: 1005,
        product: "Monitor",
        category: "Electronics",
        quantity: 2,
        price: 12000,
        salesperson: "Priya",
        sale_date: ISODate("2026-03-03T00:00:00Z")
    },
    {
        sale_id: 1006,
        product: "Mouse",
        category: "Accessories",
        quantity: 10,
        price: 500,
        salesperson: "Amit",
        sale_date: ISODate("2026-03-20T00:00:00Z")
    }
])

For this lesson, each document represents one sales transaction. The transaction revenue is calculated as quantity × price.

Run the sample insertion once to avoid adding duplicate sample records every time you practise.

3. Calculate Total Sales Revenue

Calculate the revenue for every transaction and then the overall total:

db.sales.aggregate([
    {
        $group: {
            _id: null,
            totalRevenue: {
                $sum: {
                    $multiply: ["$quantity", "$price"]
                }
            },
            totalTransactions: {
                $sum: 1
            },
            totalItemsSold: {
                $sum: "$quantity"
            }
        }
    },
    {
        $project: {
            _id: 0,
            totalRevenue: 1,
            totalTransactions: 1,
            totalItemsSold: 1
        }
    }
])

Expected totals for the sample records:

  • Total revenue: ₹1,36,000
  • Total transactions: 6
  • Total items sold: 23

_id: null groups all matching documents into one group. $multiply calculates revenue for each transaction, and $sum adds the values together.

4. Product-Wise Sales Report

Find the total quantity sold and revenue for each product:

db.sales.aggregate([
    {
        $group: {
            _id: "$product",
            totalQuantity: {
                $sum: "$quantity"
            },
            totalRevenue: {
                $sum: {
                    $multiply: ["$quantity", "$price"]
                }
            },
            totalTransactions: {
                $sum: 1
            }
        }
    },
    {
        $sort: {
            totalRevenue: -1
        }
    }
])

Expected product revenue:

  • Laptop: ₹1,50,000
  • Monitor: ₹24,000
  • Keyboard: ₹4,500
  • Mouse: ₹7,500

The report sorts products by revenue from highest to lowest. The total revenue across these products is ₹1,86,000.

5. Category-Wise Sales Report

Calculate revenue for each product category:

db.sales.aggregate([
    {
        $group: {
            _id: "$category",
            totalQuantity: {
                $sum: "$quantity"
            },
            totalRevenue: {
                $sum: {
                    $multiply: ["$quantity", "$price"]
                }
            }
        }
    },
    {
        $sort: {
            totalRevenue: -1
        }
    }
])

Expected results:

  • Electronics: ₹1,74,000
  • Accessories: ₹12,000

This report helps a business compare the performance of different product categories.

6. Salesperson-Wise Performance Report

Calculate revenue generated by each salesperson:

db.sales.aggregate([
    {
        $group: {
            _id: "$salesperson",
            totalTransactions: {
                $sum: 1
            },
            totalQuantity: {
                $sum: "$quantity"
            },
            totalRevenue: {
                $sum: {
                    $multiply: ["$quantity", "$price"]
                }
            },
            averageTransactionValue: {
                $avg: {
                    $multiply: ["$quantity", "$price"]
                }
            }
        }
    },
    {
        $sort: {
            totalRevenue: -1
        }
    }
])

Expected total revenue by salesperson:

  • Rahul: ₹1,50,000
  • Priya: ₹49,000
  • Amit: ₹9,500

Use $avg to calculate the average transaction value for each salesperson.

7. Monthly Revenue Report

Use $dateToString to group sales by year and month.

db.sales.aggregate([
    {
        $group: {
            _id: {
                $dateToString: {
                    format: "%Y-%m",
                    date: "$sale_date",
                    timezone: "UTC"
                }
            },
            totalRevenue: {
                $sum: {
                    $multiply: ["$quantity", "$price"]
                }
            },
            totalTransactions: {
                $sum: 1
            }
        }
    },
    {
        $sort: {
            _id: 1
        }
    }
])

Expected monthly revenue:

  • 2026-01: ₹1,02,500
  • 2026-02: ₹54,500
  • 2026-03: ₹29,000

The timezone is explicitly set to UTC because the sample dates use UTC. For business reports, select the timezone appropriate to your business.

8. Filter Sales by Date

Use $match to select transactions within a date range before calculating revenue.

db.sales.aggregate([
    {
        $match: {
            sale_date: {
                $gte: ISODate("2026-01-01T00:00:00Z"),
                $lt: ISODate("2026-03-01T00:00:00Z")
            }
        }
    },
    {
        $group: {
            _id: null,
            totalRevenue: {
                $sum: {
                    $multiply: ["$quantity", "$price"]
                }
            },
            totalTransactions: {
                $sum: 1
            }
        }
    }
])

The query includes January and February 2026 but excludes March 1 and later dates.

Expected revenue for this date range: ₹1,57,000.

9. Find the Top Three Sales Transactions

Calculate transaction revenue, sort it, and display the three highest-value transactions.

db.sales.aggregate([
    {
        $project: {
            sale_id: 1,
            product: 1,
            salesperson: 1,
            quantity: 1,
            price: 1,
            revenue: {
                $multiply: ["$quantity", "$price"]
            }
        }
    },
    {
        $sort: {
            revenue: -1
        }
    },
    {
        $limit: 3
    }
])

$project calculates the revenue field. $sort places the highest values first, and $limit returns only three documents.

10. Join Sales with Product Details Using $lookup

Insert product details into the products collection:

db.products.insertMany([
    {
        product: "Laptop",
        brand: "ExampleTech",
        warranty_years: 2
    },
    {
        product: "Mouse",
        brand: "ExampleGear",
        warranty_years: 1
    },
    {
        product: "Keyboard",
        brand: "ExampleGear",
        warranty_years: 1
    },
    {
        product: "Monitor",
        brand: "ExampleView",
        warranty_years: 3
    }
])

Combine sales with product information:

db.sales.aggregate([
    {
        $lookup: {
            from: "products",
            localField: "product",
            foreignField: "product",
            as: "product_details"
        }
    },
    {
        $project: {
            _id: 0,
            sale_id: 1,
            product: 1,
            quantity: 1,
            product_details: 1
        }
    }
])

The $lookup stage matches the product field in sales documents with the product field in products documents.

In a production database, use a stable unique product identifier instead of a product name to avoid ambiguous matches.

11. Find Products with Revenue Greater Than ₹10,000

Use $group to calculate product revenue and $match to filter the grouped results.

db.sales.aggregate([
    {
        $group: {
            _id: "$product",
            totalRevenue: {
                $sum: {
                    $multiply: ["$quantity", "$price"]
                }
            }
        }
    },
    {
        $match: {
            totalRevenue: {
                $gt: 10000
            }
        }
    },
    {
        $sort: {
            totalRevenue: -1
        }
    }
])

Only products with total revenue greater than ₹10,000 will appear in the result.

12. Create an Index for Faster Date Queries

Create an index on the sales date:

db.sales.createIndex({
    sale_date: 1
})

Check existing indexes:

db.sales.getIndexes()

An index can improve date-range queries when MongoDB can use it effectively. Indexes consume storage and add work to writes, so create them according to actual query patterns.

13. Practical Assignment

  1. Create a database named salesDB.
  2. Insert at least ten sales transactions.
  3. Calculate total revenue and total items sold.
  4. Create a product-wise sales report.
  5. Generate a category-wise revenue report.
  6. Calculate salesperson-wise total revenue.
  7. Generate a monthly sales report.
  8. Filter transactions between two dates.
  9. Display the five highest-value transactions.
  10. Use $lookup to combine sales and product details.
  11. Find products with revenue greater than ₹20,000.
  12. Create an index on sale_date.

🧠 Quick Quiz

1. Which aggregation stage groups documents?




2. Which operator calculates the product of two numeric values?




3. Which aggregation stage combines matching documents from another collection?