MongoDB $minN Accumulator

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

What You’ll Learn

The $minN accumulator collects the N smallest values in each $group bucket—ideal for bottom-3 scores, lowest prices, or floor metrics without a separate $sort stage.

01

N min per group

Array of lowest values.

02

input + n

Two required properties.

03

No $sort

Compares across the group.

04

vs $min

Many floors vs one floor.

05

Nulls filtered

Skips null and missing.

06

vs $bottomN

Min values vs ranked docs.

Definition and Usage

$minN is a MongoDB accumulator used in the $group stage. For each group, it evaluates an input expression on every document, keeps the N smallest results, and returns them as an array (typically lowest first).

💡
Beginner tip

Think of $min as “give me the single lowest score” and $minN as “give me the bottom three scores.” Unlike $firstN, $minN ignores null and missing values automatically.

Use $minN for bottom-N reports, cheapest-price lists, and quality floor analysis. When you need guaranteed tie-breaking order or full documents at each rank, prefer $bottomN with an explicit sortBy.

📝 Syntax

As a $group accumulator, $minN requires input and n:

mongosh
{
  $group: {
    _id: <expression>,
    <field>: {
      $minN: {
        input: <expression>,
        n: <positive integer expression>
      }
    }
  }
}

Syntax Rules

  • input — expression evaluated per document: field path, projection object, or array like ["$score", "$playerId"].
  • n — positive integer; how many minimum values to keep. Can be constant or depend on _id.
  • Array result — unlike $min, output is always an array (up to n elements).
  • Null filtering — null and missing input values are excluded (unlike $firstN / $lastN).
  • Fewer than N — if fewer valid values exist, returns all available non-null elements.
  • Version — available in MongoDB 5.2 and later.
mongosh
db.gamescores.aggregate([
  {
    $group: {
      _id: "$gameId",
      bottomThree: {
        $minN: {
          input: "$score",
          n: 3
        }
      }
    }
  }
]);

⚡ Quick Reference

QuestionAnswer
Stage$group accumulator
Required keysinput, n
ReturnsArray of up to N smallest values
Needs $sort?No—compares all docs in group
Null / missingFiltered out
MongoDB version5.2+
Bottom 3
n: 3

Three smallest values

Score only
input: "$score"

Scalar per document

Score + player
input: [
  "$score",
  "$playerId"
]

Tuple per low score

Dynamic n
n: {
  $cond: [
    { $eq: ["$gameId", "G2"] },
    1, 3
  ]
}

n from group key

🧰 Parameters

The $minN accumulator object has two required properties:

input Required

Expression evaluated on each document. MongoDB compares all values in the group and retains the N smallest non-null results.

input: "$score"
input: ["$score", "$playerId"]
n Required

Positive integer limiting how many minimum values to return. Can be a constant or an expression tied to the group _id.

n: 5
n: { $cond: [ …, 1, 3 ] }
null handling Behavior

Null and missing values are filtered out. If you request n: 4 but only three documents have scores, you get three elements.

// null scores excluded
memory limit Edge case

Each group is subject to the 100 MB aggregation memory limit. Very large groups may fail if exceeded.

$match before $group

Examples Gallery

Game scores grouped by gameId—find the bottom three scores per game with scalar and tuple inputs.

📚 Getting Started

Sample game scores and the core $minN grouping pattern.

Example 1 — Sample gamescores collection

mongosh
db.gamescores.insertMany([
  { playerId: "PlayerA", gameId: "G1", score: 31 },
  { playerId: "PlayerB", gameId: "G1", score: 33 },
  { playerId: "PlayerC", gameId: "G1", score: 99 },
  { playerId: "PlayerD", gameId: "G1", score: 1 },
  { playerId: "PlayerA", gameId: "G2", score: 10 },
  { playerId: "PlayerB", gameId: "G2", score: 14 },
  { playerId: "PlayerC", gameId: "G2", score: 66 },
  { playerId: "PlayerD", gameId: "G2", score: 80 }
]);

How It Works

Four players per game—G1 bottom three are 1, 31, 33; G2 bottom three are 10, 14, 66.

Example 2 — Bottom three scores in one game

mongosh
db.gamescores.aggregate([
  { $match: { gameId: "G1" } },
  {
    $group: {
      _id: "$gameId",
      bottomThree: {
        $minN: {
          input: ["$score", "$playerId"],
          n: 3
        }
      }
    }
  }
]);

/* Result:
[
  {
    _id: "G1",
    bottomThree: [
      [1, "PlayerD"],
      [31, "PlayerA"],
      [33, "PlayerB"]
    ]
  }
]
*/

How It Works

Tuple input pairs each score with the player id—useful for lowest-scorer displays without a second lookup.

📈 Practical Patterns

Multiple games, compare with $min, and vary n per group.

Example 3 — Bottom three scores per game (all groups)

mongosh
db.gamescores.aggregate([
  {
    $group: {
      _id: "$gameId",
      lowScores: {
        $minN: {
          input: ["$score", "$playerId"],
          n: 3
        }
      }
    }
  },
  { $sort: { _id: 1 } }
]);

/* G1: [ [1,"PlayerD"], [31,"PlayerA"], [33,"PlayerB"] ]
   G2: [ [10,"PlayerA"], [14,"PlayerB"], [66,"PlayerC"] ] */
*/

How It Works

Each gameId gets its own bottom-3 array independently—no $sort before $group is required.

Example 4 — $minN vs $min

mongosh
db.gamescores.aggregate([
  { $match: { gameId: "G1" } },
  {
    $group: {
      _id: "$gameId",
      floorScore: {
        $min: "$score"
      },
      bottomThreeScores: {
        $minN: {
          input: "$score",
          n: 3
        }
      }
    }
  }
]);

/* floorScore: 1
   bottomThreeScores: [1, 31, 33] */
*/

How It Works

Both scan the same group. $min returns one floor; $minN returns the full bottom-N list in one stage.

Example 5 — Dynamic n based on group key

Return 1 lowest score for game G2 but 3 for every other game:

mongosh
db.gamescores.aggregate([
  {
    $group: {
      _id: { gameId: "$gameId" },
      lowScores: {
        $minN: {
          input: ["$score", "$playerId"],
          n: {
            $cond: {
              if: { $eq: ["$gameId", "G2"] },
              then: 1,
              else: 3
            }
          }
        }
      }
    }
  },
  { $sort: { "_id.gameId": 1 } }
]);

/* G1 → [ [1,"PlayerD"], [31,"PlayerA"], [33,"PlayerB"] ]
   G2 → [ [10,"PlayerA"] ] */
*/

How It Works

n can depend on _id—handy when different categories need different bottom-N depths in one pipeline.

🧠 How $minN Works

1

Documents bucketed

$group assigns each document to a bucket via _id.

Group
2

Input evaluated

Each document’s input expression is computed; null/missing values are dropped.

Evaluate
3

Bottom N retained

MongoDB compares all values using BSON ordering and keeps the N smallest.

Compare
=

Array returned

Up to n elements per group—smallest values first in typical numeric cases.

📝 Notes

  • $minN requires MongoDB 5.2+ as a $group accumulator.
  • No $sort required—comparison happens across the entire group.
  • Null and missing values are excluded—different from $firstN / $lastN.
  • Result is an array per group; use $min for a single scalar floor.
  • Groups with fewer than n valid values return all available non-null elements.
  • Large groups are subject to the 100 MB per-group aggregation memory limit.
  • Previous topic: $min. Next: $push.

Conclusion

$minN extends $min to return the bottom N values per group in one accumulator—no pre-sort needed. Set input and n, and MongoDB handles the comparison.

Need only the single floor? Use $min. Need guaranteed ranked documents with tie rules? Use $bottomN. Next: $push for collecting values into arrays.

💡 Best Practices

✅ Do

  • Use tuple input: ["$score", "$playerId"] to attach context to each low value
  • Combine $min + $minN when dashboards need floor and bottom-N together
  • Put $match before $group to shrink groups and avoid memory pressure
  • Use $bottomN when tie order must follow explicit sortBy rules
  • Test with groups that have fewer than n valid values to confirm array length

❌ Don’t

  • Confuse $minN with $min (array vs single value)
  • Expect null scores to appear in the result—they are filtered out
  • Assume output order on tied equal values—use $bottomN for strict ordering
  • Compare mixed BSON types without understanding type ordering rules
  • Deploy on MongoDB versions before 5.2 without a fallback pipeline

Key Takeaways

Knowledge Unlocked

Five things to remember about $minN

Use these points when building bottom-N min reports inside $group.

5
Core concepts
📄 02

input + n

Two required keys.

Syntax
📊 03

No $sort

Full group compare.

Pattern
👤 04

Nulls out

Filtered automatically.

Behavior
📥 05

vs $bottomN

Min vs ranked docs.

Choose

❓ Frequently Asked Questions

$minN returns an array of the N smallest input values from each $group bucket. It compares values across all documents in the group and keeps the bottom N—no $sort stage required.
Inside $group: { bottomThree: { $minN: { input: "$score", n: 3 } } }. Both input and n are required. It also works as an aggregation expression and window operator.
$min returns a single lowest value. $minN returns an array of up to N smallest values. Use $min for the floor alone; use $minN for a bottom-N list of scores or prices.
$minN finds the N minimum values by comparison without requiring sortBy. $bottomN ranks inside $group with sortBy and returns the bottom N documents. Use $bottomN when you need a guaranteed sort order on ties.
No. Unlike $firstN and $lastN, $minN filters out null and missing values. If only three documents have scores and n is 4, you get an array of three elements.
$minN returns all available non-null values—never more than exist. A group with two numeric scores and n: 3 yields an array of two items.
Did you know?

$minN and $maxN were added in MongoDB 5.2 alongside $firstN, $lastN, $topN, and $bottomN—replacing fragile sort-and-slice recipes for bottom-N numeric reports. See the official $minN docs.

Continue the Accumulators Series

Build bottom-N min arrays with $minN, then learn $push for collecting every value into an array.

Next: $push →

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