BugForge
All lessons
Databases · 08/09 6 min1 hands-on

Reports with aggregate

Group, sum, count and rank with a pipeline: the query behind every dashboard.

find returns documents. Aggregation returns answers: totals per category, top customers, average order value.

A pipeline is a list of stages

Documents flow through the stages in order, like water through filters.

Order.aggregate([
  { $match: { status: "paid" } },                       // 1. keep paid orders
  { $group: {                                           // 2. one row per category
      _id: "$category",
      total: { $sum: "$amount" },
      count: { $sum: 1 },
  } },
  { $sort: { total: -1 } },                             // 3. biggest first
  { $limit: 5 },                                        // 4. top five
]);
// → [{ _id: "games", total: 160, count: 2 }, …]

Reading $group

  • _id is what you group by. "$category" means "the value of the category field". Use null to group everything into one row.
  • Each other key is an accumulator: $sum, $avg, $min, $max, $push, $first.
  • { $sum: 1 } adds 1 per document: a count.

Stage cheat sheet

Stage Does
$match filter (same syntax as find)
$group combine rows
$sort order (1 up, -1 down)
$limit / $skip top-n, paging
$project pick or rename fields
$unwind one row per array element

Put $match first: filtering early means less work for every later stage.

Your turn · 1 exercise0/1 solved

Your first report

Group orders: totalsByCategory() returns { _id: category, total, count } sorted by total, highest first. topCustomers(n) returns the n biggest spenders as { _id: customer, spent }.

Loading editor…
Next in Databases
Database errors to status codes