100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
MongoDB

Grouping and Accumulators

Master the $group stage and its accumulator operators to compute sums, averages, counts, and other summaries across groups of documents.

AggregationIntermediate10 min readJul 10, 2026
Analogies

The $group Stage and the _id Field

The $group stage collects documents that share a common value into buckets and produces one output document per bucket. The _id field in a $group specification defines the grouping key: it can be a single field reference like "$customerId", a compound object combining multiple fields for multi-level grouping, or the literal value null to collapse the entire input into a single group. Every other field in the $group specification must be an accumulator expression, since $group's job is specifically to summarize many documents into fewer, richer ones.

🏏

Cricket analogy: Grouping every delivery bowled in a tournament by bowler name to compute each bowler's total wickets mirrors $group bucketing documents by a shared key like "$bowlerId".

Common Accumulator Operators

Accumulators compute a value across all documents in a group: $sum adds numeric values (or counts documents when given the literal 1), $avg computes a mean, $min and $max find extremes, $push collects values into an array preserving duplicates, and $addToSet collects unique values into an array. $first and $last, when used after a $sort stage, capture the first or last document's value within each group, which is a common way to get, for example, the most recent order per customer. Because $group operates on documents already grouped in memory, the accumulators run once per group rather than once per document, so a group's cost scales with the group's size, not the whole collection.

🏏

Cricket analogy: Computing a batter's career average by summing all runs and dividing by innings played mirrors $avg, while collecting every unique venue they've played at mirrors $addToSet.

javascript
db.sales.aggregate([
  { $sort: { date: -1 } },
  { $group: {
      _id: "$region",
      totalRevenue: { $sum: "$amount" },
      avgOrderValue: { $avg: "$amount" },
      orderCount: { $sum: 1 },
      largestOrder: { $max: "$amount" },
      latestOrderDate: { $first: "$date" },
      distinctProducts: { $addToSet: "$productId" }
  }}
]);

$first and $last only produce meaningful results when a $sort stage immediately precedes $group in the pipeline; without a defined order, "first" and "last" reflect whatever order documents happened to arrive in, which is not guaranteed to be stable.

Multi-Field Grouping and Reshaping After $group

Setting _id to a compound object such as { year: { $year: "$date" }, region: "$region" } produces one bucket per unique combination of year and region, enabling multi-dimensional summaries like monthly sales per region. Because $group replaces the document shape entirely — the output documents contain only _id and the accumulator fields you defined — a $project stage typically follows $group to rename _id's subfields into a flatter, more client-friendly structure, since consumers of an API rarely want to dig through a nested _id object.

🏏

Cricket analogy: Grouping deliveries by both bowler and match format (Test, ODI, T20) to see format-specific averages mirrors compound _id grouping combining two keys into one bucket.

After a compound $group, chain a $project stage like { $project: { _id: 0, year: "$_id.year", region: "$_id.region", totalRevenue: 1 } } to flatten the nested _id into top-level fields before returning results to a client.

  • $group buckets documents by an _id expression, which can be a single field, a compound object, or null for a single overall group.
  • Every non-_id field in a $group specification must be an accumulator expression.
  • $sum, $avg, $min, and $max compute numeric summaries; $push and $addToSet collect values into arrays, with $addToSet deduplicating.
  • $first and $last require a preceding $sort stage to produce meaningful, stable results.
  • A compound _id object enables multi-dimensional grouping, such as grouping by both region and year.
  • $group output documents contain only _id and the defined accumulator fields, replacing the original document shape.
  • A $project stage commonly follows $group to flatten a compound _id into simpler top-level fields for API consumers.

Practice what you learned

Was this page helpful?

Topics covered

#MongoDB#MongoDBStudyNotes#Database#GroupingAndAccumulators#Grouping#Accumulators#Group#Stage#StudyNotes#SkillVeris