$group

Grouping and Accumulator Expressions

$group takes an _id saying what makes two documents the same, and accumulators that fold every document in a group into one value. The output carries the group key as _id plus what the accumulators produced. { $sum: 1 } counts, because it adds the constant 1 once per document.

Revenue and the priciest item in each product category
db.orders.aggregate([
  { $unwind: '$items' },
  { $group: { _id: '$items.category', units: { $sum: '$items.qty' },
              best: { $top: { output: '$items.sku', sortBy: { 'items.price': -1 } } },
              avg: { $avg: '$items.price' } } },
  { $sort: { _id: 1 } }
])
Output
[
  { _id: 'accessories', units: 16, best: 'AC-51', avg: 26.25 },
  { _id: 'audio', units: 9, best: 'AU-31', avg: 120 },
  { _id: 'displays', units: 6, best: 'DS-42', avg: 448 },
  { _id: 'keyboards', units: 6, best: 'KB-11', avg: 108 }
]

The _id can be any expression. null folds the whole stream into one document; a subdocument makes a compound key that stays nested, so later stages address it as '_id.status'; and a computed value such as { $dateToString: { format: '%Y-%m', date: '$placedAt' } } buckets by month.

Accumulators available inside $group
Accumulator Notes
$sum, $avg, $min, $max Ignore missing values; BSON type order applies
$count Shorthand for { $sum: 1 } (5.0+)
$push, $addToSet Build arrays; $addToSet is unordered
$first, $last Meaningful only after an explicit $sort
$top, $topN, $bottom, $bottomN Carry their own sortBy (5.2+)
$stdDevPop, $stdDevSamp, $median Also $percentile; t-digest based (7.0+)
$mergeObjects Merges subdocuments, later keys winning

$top is the one to learn first, because the obvious alternative is worse: sorting the whole stream by price and taking $first forces a blocking sort, while $top keeps a single candidate per group.