MongoDB $min Accumulator

Beginner
⏱️ 8 min read
📚 Updated: Jul 2026
🎯 5 Examples
Aggregation

What You’ll Learn

The $min accumulator finds the lowest value in each $group bucket—ideal for cheapest prices, minimum scores, floor quantities, and range reports alongside $max.

01

Floor per group

Smallest value in the bucket.

02

Simple syntax

{ $min: "$field" }

03

No $sort needed

Scans all docs in group.

04

Expressions OK

Min of computed values.

05

vs $first

Floor value vs first doc.

06

Null handling

Skips null when others exist.

Definition and Usage

$min is a MongoDB accumulator used in the $group stage. For each group, it evaluates an expression on every document and returns the minimum value found.

💡
Beginner tip

Unlike $first or $last, $min does not care about document order—it compares values across the whole group. Prices 25, 15, 20, and 10 yield 10 whether or not you sorted first.

Use $min for price floors, minimum test scores, lowest inventory levels, and quality thresholds. Pair with $max for min/max ranges, or use $bottomN when you need the full documents at the bottom of a ranked list.

📝 Syntax

$min takes one expression inside $group:

mongosh
{
  $group: {
    _id: <expression>,
    <outputField>: { $min: <expression> }
  }
}

Syntax Rules

  • Stage — primary use as accumulator in $group (also $bucket, windows).
  • Expression — field path like "$price" or a formula like { $multiply: ["$price", "$quantity"] }.
  • Output — the lowest value found, or null if no usable values exist.
  • Comparison — uses BSON comparison order; mixed types compare by type ranking, not just numeric magnitude.
  • Null / missing — ignored when at least one non-null value exists in the group.
  • _id: null — one global minimum across all documents.
mongosh
db.products.aggregate([
  {
    $group: {
      _id: null,
      minPrice: { $min: "$price" }
    }
  }
]);

⚡ Quick Reference

QuestionAnswer
Stage$group accumulator
Syntax{ $min: <expression> }
Needs $sort?No—scans entire group
Empty / all nullReturns null
vs $max$min = lowest; $max = highest
vs $first$min = floor anywhere; $first = value on first doc
Global min
{ _id: null,
  min: { $min: "$price" } }

One floor for all docs

By category
{ _id: "$category",
  min: { $min: "$price" } }

Min per category

Expression
{ $min: {
  $multiply: ["$price", "$qty"]
} }

Min of computed total

Min + max
low:  { $min: "$price" }
high: { $max: "$price" }

Range in one $group

🧰 Parameters

$min accepts one expression inside $group:

expression Required

Value compared for each document in the group. Can be a field path or any expression MongoDB can compare using BSON ordering rules.

{ $min: "$price" }
{ $min: { $add: ["$base", "$discount"] } }
_id Group key

Defines buckets. Use a field path for per-category minimums, compound keys for multi-field grouping, or null for one global bucket.

_id: "$category"
return type Value | null

Returns the winning value’s type (number, date, string, etc.). With mixed types, BSON comparison order determines the result type.

10
null / missing Important

If some documents have values, null and missing fields are skipped. If all are null or missing, result is null.

$match: { price: { $type: "number" } }

Examples Gallery

Product prices and student scores—find global and per-group minimums, use expressions, and compare with related operators.

📚 Getting Started

Insert sample products and find the lowest price overall.

Example 1 — Sample products collection

mongosh
db.products.insertMany([
  { name: "Product A", category: "Electronics", price: 25 },
  { name: "Product B", category: "Electronics", price: 15 },
  { name: "Product C", category: "Books",       price: 20 },
  { name: "Product D", category: "Books",       price: 10 }
]);

How It Works

Four products across two categories—the global minimum price is Product D at 10; Electronics min is 15.

Example 2 — Lowest price overall

mongosh
db.products.aggregate([
  {
    $group: {
      _id: null,
      minPrice: { $min: "$price" }
    }
  }
]);

/* Result:
{ _id: null, minPrice: 10 }
   — Product D has the lowest price */
*/

How It Works

_id: null groups every document together. $min compares all price values and returns 10.

📈 Practical Patterns

Break minimums down by category, compute on expressions, and compare operators.

Example 3 — Min price per category (with $max)

mongosh
db.products.aggregate([
  {
    $group: {
      _id: "$category",
      minPrice: { $min: "$price" },
      maxPrice: { $max: "$price" }
    }
  },
  { $sort: { _id: 1 } }
]);

/* Result:
[
  { _id: "Books",       minPrice: 10, maxPrice: 20 },
  { _id: "Electronics", minPrice: 15, maxPrice: 25 }
]
*/

How It Works

Grouping by category gives independent min/max price ranges—common for catalog and pricing analysis.

Example 4 — Min line total per product (expression)

Find the smallest price × quantity per item:

mongosh
db.sales.insertMany([
  { item: "abc", price: 10, quantity: 2 },
  { item: "jkl", price: 20, quantity: 1 },
  { item: "xyz", price: 5,  quantity: 5 },
  { item: "abc", price: 10, quantity: 10 },
  { item: "xyz", price: 5,  quantity: 10 }
]);

db.sales.aggregate([
  {
    $group: {
      _id: "$item",
      minTotal: {
        $min: { $multiply: ["$price", "$quantity"] }
      },
      minQty: { $min: "$quantity" }
    }
  },
  { $sort: { _id: 1 } }
]);

/* abc → minTotal: 20 (10×2), minQty: 2
   jkl → minTotal: 20,         minQty: 1
   xyz → minTotal: 25 (5×5),   minQty: 5 */
*/

How It Works

$min accepts any expression—not just a field path. MongoDB evaluates $multiply per document, then picks the smallest result.

Example 5 — $min vs $first

The lowest value is not always on the first document:

mongosh
db.students.insertMany([
  { name: "Alice",   class: "10A", score: 85 },
  { name: "Bob",     class: "10A", score: 92 },
  { name: "Charlie", class: "10A", score: 78 }
]);

db.students.aggregate([
  { $sort: { class: 1, score: 1 } },
  {
    $group: {
      _id: "$class",
      minScore:       { $min: "$score" },
      firstDocScore:  { $first: "$score" }
    }
  }
]);

/* 10A (sorted asc by score: 78, 85, 92):
   minScore: 78       — Charlie's score
   firstDocScore: 78  — same here (lowest is first)

   If sorted by name instead, firstDocScore might be 85 (Alice)
   while minScore stays 78 */
*/

How It Works

Use $min when you need the floor. Use $first when you need the value tied to the earliest (sorted) record—they answer different questions.

🧠 How $min Works

1

Documents bucketed

$group assigns each document to a bucket via _id.

Group
2

Expression evaluated

For each document, MongoDB computes the $min expression (field or formula).

Evaluate
3

Values compared

MongoDB tracks the running minimum using BSON comparison rules across all documents in the bucket.

Compare
=

Minimum returned

One floor value per group—or null if no comparable values exist.

📝 Notes

  • $min does not require $sort—it scans the entire group.
  • Returns null when every document has null or missing values for the expression.
  • With mixed BSON types, comparison follows type order—not intuitive numeric min across strings and numbers.
  • Tied equal values: MongoDB may return any of the ties—no guaranteed pick.
  • In $group, array fields are compared as whole arrays, not element-by-element.
  • Previous topic: $mergeObjects. Next: $minN.

Conclusion

$min is the go-to accumulator for floor values inside $group. It is simple, order-independent, and works on field paths or expressions like $multiply.

Pair with $max for ranges, use $bottom when you need the full lowest-ranked document, or explore $minN for the N smallest values per group.

💡 Best Practices

✅ Do

  • Use $min + $max in one $group for price/score ranges
  • Filter with $match before $group to min only relevant documents
  • Use expressions when the floor of a computed value matters (line totals, durations)
  • Validate numeric types with $match: { field: { $type: "number" } } when data is messy
  • Use $bottom or $bottomN when you need identifying fields from the lowest record

❌ Don’t

  • Confuse $min with $first (floor vs first document’s value)
  • Assume $min returns the product name—it returns the minimum value only
  • Compare mixed types without understanding BSON type ordering
  • Expect $min to traverse into array elements inside $group
  • Use $min when you need N smallest values—use $minN instead

Key Takeaways

Knowledge Unlocked

Five things to remember about $min

Use these points when finding floor values inside $group.

5
Core concepts
📝 02

Simple syntax

{ $min: "$field" }

Syntax
📊 03

No $sort

Scans whole group.

Pattern
🔄 04

vs $first

Floor vs leading doc.

Compare
💲 05

+ $max

Min/max ranges.

Pair

❓ Frequently Asked Questions

$min returns the lowest value of an expression across all documents in each $group bucket. It scans every document in the group and picks the minimum—no $sort required.
Inside $group: { minPrice: { $min: "$price" } }. It also works as an expression in $project, $addFields, and window stages—but this tutorial focuses on the $group accumulator.
Grouping with _id: null puts all documents into one bucket, so $min returns a single overall minimum for the entire filtered collection.
If some documents have values and others are null or missing, $min ignores the null/missing ones. If every document lacks a usable value, $min returns null.
$min finds the smallest value anywhere in the group. $first returns a field from the first document in pipeline order—they differ when the lowest value is not on the first document.
$min returns the lowest value; $max returns the highest. Use both in the same $group for range summaries (min price and max price per category).
Did you know?

$min and $max use BSON comparison order, so dates, strings, and numbers compare by type rules—not just numeric magnitude. For the N smallest numbers specifically, MongoDB 5.2+ offers $minN. See the official $min docs.

Continue the Accumulators Series

Find floor values with $min, then learn $minN for the N smallest values per group.

Next: $minN →

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.

5 people found this page helpful