MongoDB $stdDevSamp Accumulator

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

What Is $stdDevSamp?

$stdDevSamp is a MongoDB accumulator for the $group stage. For each group it returns the sample standard deviation of numeric values—how spread out the numbers are around their mean when the group is a sample used to estimate a larger population.

Remember
$stdDevSamp = sample standard deviation

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

non-numeric / null → ignored
1 value only → null  (needs at least 2)
vs $stdDevPop → divides by N (population)
UsePrefer
Estimate spread from a sample$stdDevSamp
Spread of a complete dataset$stdDevPop
Center (mean) only$avg

How to Use $stdDevSamp in MongoDB

Pass one numeric expression inside $group.

  1. Put $stdDevSamp 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, …)
$stdDevSampYesNumeric expression to measure
ExpressionYesUsually "$field"; may be computed

Pseudocode

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

Cheat Sheet

Keep these facts handy while measuring sample spread.

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

Live Preview

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

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

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

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

Worked Walkthrough — Quiz 1

Three scores: 85, 90, 71. Follow the sample formula (divide by N−1).

Calculation
scores: 85, 90, 71
N = 3

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

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

variance (sample) = 194 / (3 − 1) = 97
stdDevSamp = √97 ≈ 9.8489

Compare population:
  $stdDevPop would use 194 / 3 ≈ 8.0416

Output:
  { _id: 1, stdDev: 9.848857801796104 }

MongoDB Examples

Same quiz-scores collection as the $stdDevPop page. First we measure sample 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 treated as a sample of a larger class. 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: $stdDevSamp measures sample standard deviation.

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

Example 2 — Overall Sample Spread

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

mongosh
db.users.aggregate([
  {
    $group: {
      _id: null,
      stdDev: { $stdDevSamp: "$score" },
      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. Sample formula. MongoDB uses divide-by-(N−1) for $stdDevSamp.
  4. Larger than population. With the same scores, sample stddev is larger than $stdDevPop (~8.18) because N−1 shrinks the denominator.
  5. Mean for context. $avg shows the center; $stdDevSamp shows estimated spread.

Example 3 — Sample Spread per Quiz

Goal: sample standard deviation for each quiz separately. Both quizzes share the same ≈ 9.8489 result with this sample.

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

How It Works

  1. Split by quiz. _id: "$quiz" creates groups 1 and 2.
  2. Three scores each. Enough for N−1 (denominator 2).
  3. Sample variance. Quiz 1: 194 / 2 = 97, then √97 ≈ 9.8489.
  4. Sort for reading. $sort orders quiz numbers ascending.
  5. One value only? A quiz with a single numeric score would return null.

Edge Cases & Pitfalls

Check these before shipping a sample-spread report.

samp vs pop

Pick sample vs population correctly

Use $stdDevSamp when estimating a larger population. Use $stdDevPop when the group is the complete dataset.

single

One numeric value → null

Unlike $stdDevPop (which returns 0), sample stddev needs at least two numbers. Plan for null in sparse groups.

null

Non-numerics are ignored

Null, missing, and string scores do not enter the math. If fewer than two numerics remain, the result is null.

array

Arrays in $group are not traversed

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

Performance Notes

ApproachCostBest for
$stdDevSampNative one-pass accumulatorSample spread (N−1)
$stdDevPopSame class of costPopulation spread (N)
$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: sample standard deviation inside $group.
  • Formula: √(sum((x−mean)²) / (N−1)).
  • vs population: use $stdDevPop when the group is complete.
  • Edge: needs ≥ 2 numerics; one value returns null.

One line: $stdDevSamp estimates how spread out a larger population is from a sample of numbers (N−1).

Frequently Asked Questions

$stdDevSamp calculates the sample standard deviation of numeric values in each $group bucket. It measures spread around the mean using the N−1 formula, which estimates variability for a larger population from a sample.
Inside $group: { spread: { $stdDevSamp: "$score" } }. It also works in $project and window stages, but this page focuses on the $group accumulator.
$stdDevSamp divides by N−1 (sample). $stdDevPop divides by N (population). Use $stdDevSamp when your group is a sample you want to generalize from; use $stdDevPop when the group is the complete dataset.
Non-numeric values—including null, missing fields, and strings—are ignored. If no numeric values exist in a group, $stdDevSamp returns null.
$stdDevSamp returns null. A sample needs at least two numeric values to estimate spread with N−1.
$avg returns the mean (center). $stdDevSamp returns the sample standard deviation (spread). Pair both in one $group for mean-and-variability reports.

Next: $sum

Add up numeric values for each group.

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