MongoDB $sum Accumulator

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

What Is $sum?

$sum is a MongoDB accumulator for the $group stage. For each group it returns the total of numeric values from an expression.

Remember
$sum = add numeric values per group

{ $sum: "$amount" }  → total of amount
{ $sum: 1 }          → count documents in the group

null / missing / non-numeric → contribute 0
all non-numeric → 0

vs $avg → mean instead of total
UsePrefer
Total amount, quantity, revenue$sum
Average amount$avg
Custom multi-step total$accumulator

How to Use $sum in MongoDB

Pass a field, a constant, or any numeric expression.

  1. Put $sum inside $group on an output field.
  2. Pass "$amount" to total a field, or 1 to count documents.
  3. Set _id to the group key, or null for one overall total.
  4. Optionally $match first so you sum only the rows you care about.
PieceRequired?Role
$group._idYesGroup key ("$category", null, …)
$sumYesExpression or constant to add
Common forms—"$field", 1, or { $multiply: [...] }

Pseudocode

Pseudocode
for each group:
    total = 0
    for each document in group:
        value = evaluate(expression)
        if value is numeric:
            total = total + value
        // else: add 0
    emit { _id: groupKey, field: total }

Cheat Sheet

Keep these facts handy while writing a total.

TopicDetail
Stage$group accumulator (also usable in $project)
Syntax{ $sum: "$field" } or { $sum: 1 }
null / missingContribute 0 to the total
Count docs{ $sum: 1 }
vs $avgTotal vs mean
Sample check100 + 150 + 200 + 50 = 500

Live Preview

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

Simulates adding each amount into a running total.

Result
+ 100 (food) → 100
+ 150 (food) → 250
+ 200 (travel) → 450
+ 50 (food) → 500

{ _id: null, totalAmount: 500 }

Worked Walkthrough — Overall Total

Same four purchases as the examples. Watch the total grow from 0 to 500.

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

All docs (_id: null):
  100 + 150 + 200 + 50 = 500

Food only:
  100 + 150 + 50 = 300

Travel only:
  200

Output (all docs):
  { _id: null, totalAmount: 500 }

MongoDB Examples

We use a tiny shopping list of four purchases. First we total every amount. Then we total per category. Finally we count documents with $sum: 1. 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
Four purchases:

  food   100
  food   150
  travel 200
  food    50

Next: $sum amounts → 500

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 $sum in the next examples.

Quick math: all amounts 100 + 150 + 200 + 50 = 500; food only 300; travel 200.

Example 2 — Overall Total

Goal: one total 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,
      totalAmount: { $sum: "$amount" }
    }
  }
]);

How It Works

  1. One bucket. _id: null groups every document together.
  2. Read each amount. $sum: "$amount" pulls the numeric field from each receipt.
  3. Add them up. 100 + 150 + 200 + 50 = 500.
  4. Need the mean instead? Use { $avg: "$amount" } (result would be 125).

Example 3 — Total per Category

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

CategoryAmountsTotal
food100, 150, 50300
travel200200
mongosh
db.transactions.aggregate([
  {
    $group: {
      _id: "$category",
      totalAmount: { $sum: "$amount" }
    }
  },
  { $sort: { _id: 1 } }
]);

How It Works

  1. Split into buckets. _id: "$category" creates separate groups for food and travel.
  2. Sum inside each bucket. Food: 300. Travel: 200.
  3. Sort for stable reading. $sort orders the group keys alphabetically.
  4. Same operator, different key. Only _id changed from Example 2.

Example 4 — Count Documents with $sum: 1

Goal: how many receipts per category. { $sum: 1 } adds one for every document—a simple document count.

mongosh
db.transactions.aggregate([
  {
    $group: {
      _id: "$category",
      orderCount: { $sum: 1 },
      totalAmount: { $sum: "$amount" }
    }
  },
  { $sort: { _id: 1 } }
]);

How It Works

  1. Same groups. Still one bucket per category.
  2. Add 1 per document. Food has three receipts → orderCount: 3.
  3. Total alongside count. You can use two $sum fields in the same $group.
  4. Why not always $count? The $count stage counts the whole pipeline result. Inside $group, { $sum: 1 } is the usual per-bucket count.

Edge Cases & Pitfalls

Check these before shipping a totals report.

null

Null and missing add nothing

They contribute 0. An empty numeric set still yields 0, not null.

types

Strings are not added

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

avg

Do not confuse with $avg

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

count

$sum: 1 counts documents

Use it inside $group for per-bucket counts. It is not the same as summing a field named 1.

Performance Notes

ApproachCostBest for
$sumNative, one pass per groupTotals and document counts
$avgSimilar native costMeans over numeric fields
$accumulatorJS per documentCustom rollups only

Prefer native $sum over a custom JavaScript reducer for plain totals. Filter early with $match so fewer documents enter the group.

Key Takeaways

  • Role: numeric total inside $group.
  • Count: { $sum: 1 } counts documents per group.
  • Nulls: contribute 0; empty numeric set returns 0.
  • vs $avg: total for sums; mean for averages.

One line: $sum is the built-in adder for each $group bucket—totals fields or counts docs with 1.

Frequently Asked Questions

$sum totals numeric values of an expression across all documents in each $group bucket. Non-numeric values are ignored (treated as zero contribution).
Inside $group: { total: { $sum: "$amount" } }. It also works as an expression in $project. This page focuses on the $group accumulator.
{ $sum: 1 } adds 1 for every document in the group, so the result is a document count. It is a common way to count rows per group.
Null and missing values do not change the total (they contribute 0). If every value is non-numeric, $sum returns 0.
$sum returns a total. $avg returns the mean (total ÷ count of numerics). Use $sum for revenue; use $avg for average order size.
Yes. Pass any numeric expression, for example { $sum: { $multiply: ["$price", "$qty"] } } to total line amounts.

Next: $top

Return the highest-ranked document in each group.

$top 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