$min is a MongoDB accumulator for the $group stage. For each group it returns the lowest value of an expression—no $sort required.
Remember
$min = lowest value per group
compare every non-null input → keep the smallest
null / missing → ignored (unless all are null → null)
vs $max → highest value
vs $minN → N smallest values as an array
vs $bottom → whole document, not a bare value
Pass a field path (e.g. "$amount") or a numeric expression.
Set _id to the group key, or null for one overall minimum.
Optionally $match first so you compare only the rows you care about.
Piece
Required?
Role
$group._id
Yes
Group key ("$category", null, …)
$min
Yes
Expression whose lowest value to keep
Expression
Yes
Usually "$field"; may be computed
Pseudocode
Pseudocode
for each group:
minVal = unset
for each document in group:
value = evaluate(expression)
if value is not null:
if minVal is unset or value < minVal:
minVal = value
emit { _id: groupKey, field: minVal ?? null }
We use a tiny shopping list of four purchases. First we find the overall minimum amount. Then we find the minimum 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.
Sort for stable reading.$sort orders the group keys alphabetically.
Same operator, different key. Only _id changed from Example 2—$min still picks the lowest value.
Need several lows? Use $minN for an array of the N smallest amounts.
Edge Cases & Pitfalls
Check these before shipping a minimum report.
null
Null and missing are skipped
They do not become zero. Only non-null values compete. If every value is null, the result is null.
types
Mixed types use BSON order
Numbers and strings compare by type rules, not “numeric sense.” Keep the field type consistent when you can.
document
$min is a value, not a document
You get 50, not the whole receipt. Need the full row? Use $bottom with sortBy.
ties
Equal minimums are interchangeable
If two values compare equal, $min may return either. That matters mainly with collations on strings.
Analysis
Performance Notes
Approach
Cost
Best for
$min
Native, tracks one value per group
Single lowest value
$minN
Tracks up to n values
Bottom-N lists
$sort + $first
Full sort cost
Avoid when a plain $min is enough
Prefer native $min over sorting just to find a floor. Filter early with $match so fewer documents enter the group.
Remember
Key Takeaways
Role: lowest value inside $group.
Nulls: skipped; all null returns null.
vs $max / $minN: peak vs floor vs N smallest.
Document needed? Use $bottom, not $min.
One line:$min is the built-in floor for each $group bucket—one lowest value, nulls ignored.
Frequently Asked Questions
$min returns the lowest value of an expression across all documents in each $group bucket. It compares every value in the group and picks the minimum—no $sort required.
Inside $group: { minAmount: { $min: "$amount" } }. It also works as an expression in $project and $addFields, but this page focuses on the $group accumulator.
Grouping with _id: null puts every document in one bucket, so $min returns a single overall minimum for the whole input.
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 returns the lowest value; $max returns the highest. Use both in the same $group for range summaries (min and max price per category).
$min returns one lowest value. $minN returns an array of the N smallest values. Use $min for a single floor; use $minN for a short bottom list.