MongoDB $avg Accumulator

Beginner
5 min read
Updated: Oct 2026
3 examples
Live preview

What Is $avg?

$avg is a MongoDB accumulator for the $group stage. For each group it computes the arithmetic mean of numeric values: total ÷ count of numeric inputs.

Remember
$avg = mean of numeric values per group

sum   → add every numeric value
count → how many numeric values were seen
avg   → sum / count

null / missing / non-numeric → ignored (not in count)
UsePrefer
Average amount, score, price$avg
Total money or quantity$sum
Custom multi-step mean$accumulator

How to Use $avg in MongoDB

Pass one numeric field (or expression) inside $group.

  1. Put $avg inside $group on an output field.
  2. Pass a field path (e.g. "$amount") or a numeric expression.
  3. Set _id to the group key, or null for one overall average.
  4. Optionally $match first so you average only the rows you care about.
PieceRequired?Role
$group._idYesGroup key ("$category", null, …)
$avgYesNumeric expression to average
ExpressionYesUsually "$field"; may be computed

Pseudocode

Pseudocode
for each group:
    sum = 0
    count = 0
    for each document in group:
        value = evaluate(expression)
        if value is numeric:
            sum = sum + value
            count = count + 1
    avg = (count === 0) ? null : sum / count
    emit { _id: groupKey, field: avg }

Cheat Sheet

Keep these facts handy while writing an average rollup.

TopicDetail
Stage$group accumulator (also usable on arrays in $project)
Syntax{ $avg: "$field" }
Formulasum of numerics ÷ count of numerics
null / missingIgnored (not in the divisor)
Empty groupReturns null when no numeric values
Sample checkfood 100 + 150 + 50 → avg 100

Live Preview

Watch the running average update. Sample collection: food 100, food 150, travel 200, food 50.

Simulates sum / count for $avg (same idea as the mongosh examples below).

Result
+ 100 (food) → sum 100, count 1, avg 100
+ 150 (food) → sum 250, count 2, avg 125
+ 200 (travel) → sum 450, count 3, avg 150
+ 50 (food) → sum 500, count 4, avg 125

{ _id: null, avgAmount: 125 }

Worked Walkthrough — Overall Average

Same four purchases as the examples. Total 500 across 4 amounts → average 125.

Calculation
Documents:
  { amount: 100, category: "food" }
  { amount: 150, category: "food" }
  { amount: 200, category: "travel" }
  { amount:  50, category: "food" }

sum   = 100 + 150 + 200 + 50 = 500
count = 4
avg   = 500 / 4 = 125

Food only:
  sum = 300, count = 3, avg = 100

Travel only:
  sum = 200, count = 1, avg = 200

Output (all docs, _id: null):
  { _id: null, avgAmount: 125 }

MongoDB Examples

We use a tiny shopping list of four purchases. First we average every amount. Then we average per category. Run these in mongosh after inserting the sample data once.

Example 1 — Sample Data

Imagine four receipts in a transactions collection. Each document has an amount and a category.

mongosh
db.transactions.insertMany([
  { amount: 100, category: "food" },
  { amount: 150, category: "food" },
  { amount: 200, category: "travel" },
  { amount: 50, category: "food" }
]);

How the Data Is Stored in MongoDB

After the insert, MongoDB keeps 4 documents in transactions. Run find() to see them:

mongosh
db.transactions.find()

Read each document like this:

Field in MongoDBMeaningExample
amountMoney spent on this purchase100
categoryWhat the purchase was for"food"
Picture
Same four purchases:

  food:   100, 150, 50  → average later
  travel: 200           → average later

How It Works

  1. Insert once. The sample command adds 4 documents to transactions.
  2. MongoDB stores fields as written. Each document keeps the same field names and values you inserted.
  3. find() shows the same shape. What you inserted is what you get back—ready for $avg in the next examples.

Quick math: all amounts average to 500 / 4 = 125; food only 300 / 3 = 100; travel 200 / 1 = 200.

Example 2 — Overall Average

Goal: one average for the whole collection. _id: null means “put every document in one big group.”

mongosh
db.transactions.aggregate([
  {
    $group: {
      // null = one group for the whole collection
      _id: null,
      avgAmount: { $avg: "$amount" }
    }
  }
]);

How It Works

  1. One bucket. _id: null groups every document together.
  2. Read each amount. $avg: "$amount" pulls the numeric field from each receipt.
  3. Sum and count. MongoDB adds 100 + 150 + 200 + 50 = 500 and counts 4 values.
  4. Divide. 500 / 4 = 125, which appears as avgAmount.
  5. Totals vs means. For a plain total use { $sum: "$amount" } instead.

Example 3 — Average per Category

Goal: average spend for food and for travel. _id: "$category" makes a separate group for each category value.

CategoryAmountsSumCountAverage
food100, 150, 503003100
travel2002001200
mongosh
db.transactions.aggregate([
  {
    $group: {
      // One group per category value ("food", "travel", ...)
      _id: "$category",
      avgAmount: { $avg: "$amount" }
    }
  },
  { $sort: { _id: 1 } }
]);

How It Works

  1. Split into buckets. _id: "$category" creates separate groups for food and travel.
  2. Average inside each bucket. Food: 300 / 3 = 100. Travel: 200 / 1 = 200.
  3. Sort for stable reading. $sort orders the group keys alphabetically.
  4. Same operator, different key. Only _id changed from Example 2—$avg still does sum ÷ count.

Edge Cases & Pitfalls

Check these before shipping an average report.

null

Null and missing are skipped

They do not lower the average. Only numeric values enter the sum and the count.

empty

No numerics → null

If every value in a group is null, missing, or non-numeric, $avg returns null, not 0.

types

Strings are not averaged

A string like "100" is ignored. Convert with $toDouble / $convert before averaging if needed.

sum

Do not confuse with $sum

$sum answers “how much in total?” $avg answers “how much on average?”

Performance Notes

ApproachCostBest for
$avgNative, one pass per groupMeans over numeric fields
$sum + manual divideExtra fields / stagesWhen you also need the total and count
$accumulatorJS per documentCustom weighted or multi-field means

Prefer native $avg over a custom JavaScript reducer when a plain mean is enough. Filter early with $match so fewer documents enter the group.

Key Takeaways

  • Role: arithmetic mean inside $group.
  • Formula: sum of numerics ÷ count of numerics.
  • Nulls: ignored; empty numeric set returns null.
  • vs $sum: mean for averages; sum for totals.

One line: $avg is the built-in mean for each $group bucket—sum ÷ count, skipping non-numerics.

Frequently Asked Questions

$avg calculates the arithmetic mean of numeric values in each $group bucket. It totals the numbers and divides by how many numeric values it counted.
Inside $group as an accumulator, for example { avgAmount: { $avg: "$amount" } }. You can also use $avg on arrays in $project, but this page focuses on the $group form.
Grouping with _id: null puts every document in one bucket, so $avg returns a single overall average for the whole input.
Null and missing values are ignored—they do not add to the sum or the count. If a group has no numeric values, $avg returns null.
$sum totals numbers. $avg divides that total by the count of numeric values. Use $avg for means; use $sum for totals.
Yes. Pass any numeric expression, for example { $avg: { $add: ["$base", "$bonus"] } } to average base plus bonus per document.

Next: $bottom

Return the lowest-ranked document in each group.

$bottom tutorial →

About the author

Mari Selvan M P
Mari Selvan M P 🔗

Developer, cloud engineer, and technical writer

  • Experience 12 years building web and cloud systems
  • Focus Full Stack Development, AWS, and Developer Education

I write practical tutorials so students and working developers can learn by doing—from databases and APIs to deployment on AWS.

9 people found this page helpful