MongoDB $stdDevPop Accumulator

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

What Is $stdDevPop?

$stdDevPop is a MongoDB accumulator for the $group stage. For each group it returns the population standard deviation of numeric values—how spread out the numbers are around their mean when the group is the full population.

Remember
$stdDevPop = population standard deviation

mean     → average of numeric values
variance → sum( (x − mean)² ) / N     ← divide by N
stdDev   → √variance

non-numeric / null → ignored
1 value only → 0
vs $stdDevSamp → divides by N−1 (sample)
UsePrefer
Spread of a complete dataset$stdDevPop
Estimate from a sample$stdDevSamp
Center (mean) only$avg

How to Use $stdDevPop in MongoDB

Pass one numeric expression inside $group.

  1. Put $stdDevPop inside $group on an output field.
  2. Pass a field path (e.g. "$score") or a numeric expression.
  3. Set _id to the group key, or null for one overall value.
  4. Optionally pair with $avg in the same stage for mean + spread.
PieceRequired?Role
$group._idYesGroup key ("$quiz", null, …)
$stdDevPopYesNumeric expression to measure
ExpressionYesUsually "$field"; may be computed

Pseudocode

Pseudocode
for each group:
    nums = numeric values only
    if nums.length === 0: emit null
    if nums.length === 1: emit 0
    mean = sum(nums) / N
    variance = sum( (x − mean)² ) / N      // population
    emit √variance

Cheat Sheet

Keep these facts handy while measuring spread.

TopicDetail
Stage$group accumulator (also $project / windows)
Syntax{ $stdDevPop: "$field" }
Formula√( sum((x−mean)²) / N )
Non-numericIgnored; all non-numeric → null
Single valueReturns 0
Sample checkscores 85, 90, 71 → ≈ 8.0416

Live Preview

Watch population standard deviation for quiz scores. Sample: quiz 1 → 85, 90, 71; quiz 2 → 96, 77, 82.

Simulates √(sum((x−mean)²) / N) for each quiz group.

Result
quiz 1: scores [85, 90, 71], mean 82, stdDevPop ≈ 8.0416
quiz 2: scores [96, 77, 82], mean 85, stdDevPop ≈ 8.0416

[
  { _id: 1, stdDev: 8.04155872120988 },
  { _id: 2, stdDev: 8.04155872120988 }
]

Worked Walkthrough — Quiz 1

Three scores: 85, 90, 71. Follow the population formula step by step.

Calculation
scores: 85, 90, 71
N = 3

mean = (85 + 90 + 71) / 3 = 246 / 3 = 82

squared diffs:
  (85 − 82)² = 9
  (90 − 82)² = 64
  (71 − 82)² = 121
sum = 194

variance (population) = 194 / 3 ≈ 64.6667
stdDevPop = √(194 / 3) ≈ 8.0416

Output:
  { _id: 1, stdDev: 8.04155872120988 }

MongoDB Examples

We use a tiny quiz-scores collection (same idea as the MongoDB docs sample). First we measure spread for the whole set, then per quiz. Run these in mongosh after inserting the sample data once.

Example 1 — Sample Data

Imagine six quiz results. Each document has a quiz number, a name, and a score.

mongosh
db.users.insertMany([
  { name: "dave123", quiz: 1, score: 85 },
  { name: "dave2", quiz: 1, score: 90 },
  { name: "ahn", quiz: 1, score: 71 },
  { name: "li", quiz: 2, score: 96 },
  { name: "annT", quiz: 2, score: 77 },
  { name: "ty", quiz: 2, score: 82 }
]);

How the Data Is Stored in MongoDB

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

mongosh
db.users.find()

Read each document like this:

Field in MongoDBMeaningExample
nameStudent / user name"dave123"
quizWhich quiz number1
scoreQuiz score85
Picture
Quiz 1 scores: 85, 90, 71
Quiz 2 scores: 96, 77, 82

Next: $stdDevPop measures spread for the whole group.

How It Works

  1. Insert once. The sample command adds 6 documents to users.
  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 $stdDevPop in the next examples.

Example 2 — Overall Population Spread

Goal: one standard deviation for every score in the collection. _id: null puts all documents in one group.

mongosh
db.users.aggregate([
  {
    $group: {
      _id: null,
      stdDev: { $stdDevPop: "$score" },
      // handy to report alongside the spread
      avgScore: { $avg: "$score" }
    }
  }
]);

How It Works

  1. One bucket. _id: null groups all six scores together.
  2. Ignore non-numerics. Only numeric score values enter the calculation.
  3. Population formula. MongoDB uses divide-by-N (not N−1) for $stdDevPop.
  4. Mean for context. $avg in the same stage shows the center; $stdDevPop shows the spread.
  5. Sample instead? Use $stdDevSamp when these scores are only a sample of a larger set.

Example 3 — Spread per Quiz

Goal: population standard deviation for each quiz separately. Both quizzes happen to share the same ≈ 8.0416 result with this sample.

mongosh
db.users.aggregate([
  {
    $group: {
      _id: "$quiz",
      stdDev: { $stdDevPop: "$score" }
    }
  },
  { $sort: { _id: 1 } }
]);

How It Works

  1. Split by quiz. _id: "$quiz" creates groups 1 and 2.
  2. Three scores each. Quiz 1 uses 85, 90, 71; quiz 2 uses 96, 77, 82.
  3. Same formula per bucket. Mean, squared diffs, divide by N, then square root.
  4. Sort for reading. $sort orders quiz numbers ascending.
  5. One value only? A quiz with a single numeric score would return 0.

Edge Cases & Pitfalls

Check these before shipping a spread report.

pop vs samp

Pick population vs sample correctly

Use $stdDevPop when the group is the whole population. Use $stdDevSamp when estimating a larger population from a sample.

null

Non-numerics are ignored

Null, missing, and string scores do not enter the math. If none remain, the result is null.

single

One numeric value → 0

With a single point there is no spread. That is expected, not an error.

array

Arrays in $group are not traversed

If input resolves to an array inside $group, it is treated as non-numeric. Pass a scalar field path instead.

Performance Notes

ApproachCostBest for
$stdDevPopNative one-pass accumulatorPopulation spread
$stdDevSampSame class of costSample spread (N−1)
$avg aloneCheaper when spread is unusedMean-only reports

Prefer the built-in accumulator over computing variance in application code. Filter early with $match so fewer documents enter each group.

Key Takeaways

  • Role: population standard deviation inside $group.
  • Formula: √(sum((x−mean)²) / N).
  • vs sample: use $stdDevSamp when estimating from a sample.
  • Edge: non-numerics ignored; one value returns 0.

One line: $stdDevPop measures how spread out a complete group of numbers is around its mean.

Frequently Asked Questions

$stdDevPop calculates the population standard deviation of numeric values in each $group bucket. It measures how spread out the values are around their mean, treating the grouped data as the entire population.
Inside $group: { spread: { $stdDevPop: "$score" } }. It also works in $project and window stages, but this page focuses on the $group accumulator.
$stdDevPop divides by N (population). $stdDevSamp divides by N−1 (sample) when you want to estimate spread for a larger population. Use $stdDevPop when your group is the complete dataset.
Non-numeric values—including null, missing fields, and strings—are ignored. If no numeric values exist in a group, $stdDevPop returns null.
$stdDevPop returns 0. With a single data point there is no spread around the mean.
$avg returns the mean (center). $stdDevPop returns the population standard deviation (spread). Pair both in one $group for mean-and-variability reports.

Next: $stdDevSamp

Compute the sample standard deviation per group.

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