MongoDB $maxN Accumulator

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

What You’ll Learn

The $maxN accumulator collects the N largest values in each $group bucket—ideal for top-3 scores, highest prices, or peak metrics without a separate $sort stage.

01

N max per group

Array of highest values.

02

input + n

Two required properties.

03

No $sort

Compares across the group.

04

vs $max

Many peaks vs one peak.

05

Nulls filtered

Skips null and missing.

06

vs $topN

Max values vs ranked docs.

Definition and Usage

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

💡
Beginner tip

Think of $max as “give me the single highest score” and $maxN as “give me the top three scores.” Unlike $firstN, $maxN ignores null and missing values automatically.

Use $maxN for leaderboards and top-N reports. When you need guaranteed tie-breaking order or full documents at each rank, prefer $topN with an explicit sortBy.

📝 Syntax

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

mongosh
{
  $group: {
    _id: <expression>,
    <field>: {
      $maxN: {
        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 maximum values to keep. Can be constant or depend on _id.
  • Array result — unlike $max, 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",
      topThree: {
        $maxN: {
          input: "$score",
          n: 3
        }
      }
    }
  }
]);

⚡ Quick Reference

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

Three largest values

Score only
input: "$score"

Scalar per document

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

Tuple per top score

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

n from group key

🧰 Parameters

The $maxN accumulator object has two required properties:

input Required

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

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

Positive integer limiting how many maximum 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 top three scores per game with scalar and tuple inputs.

📚 Getting Started

Sample game scores and the core $maxN 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 top three are 99, 33, 31; G2 top three are 80, 66, 14.

Example 2 — Top three scores in one game

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

/* Result:
[
  {
    _id: "G1",
    topThree: [
      [99, "PlayerC"],
      [33, "PlayerB"],
      [31, "PlayerA"]
    ]
  }
]
*/

How It Works

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

📈 Practical Patterns

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

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

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

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

How It Works

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

Example 4 — $maxN vs $max

mongosh
db.gamescores.aggregate([
  { $match: { gameId: "G1" } },
  {
    $group: {
      _id: "$gameId",
      peakScore: {
        $max: "$score"
      },
      topThreeScores: {
        $maxN: {
          input: "$score",
          n: 3
        }
      }
    }
  }
]);

/* peakScore: 99
   topThreeScores: [99, 33, 31] */
*/

How It Works

Both scan the same group. $max returns one peak; $maxN returns the full top-N list in one stage.

Example 5 — Dynamic n based on group key

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

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

/* G1 → [ [99,"PlayerC"], [33,"PlayerB"], [31,"PlayerA"] ]
   G2 → [ [80,"PlayerD"] ] */
*/

How It Works

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

🧠 How $maxN 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

Top N retained

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

Compare
=

Array returned

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

📝 Notes

  • $maxN 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 $max for a single scalar peak.
  • 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: $max. Next: $mergeObjects.

Conclusion

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

Need only the single peak? Use $max. Need guaranteed ranked documents with tie rules? Use $topN. Next: $mergeObjects for combining object fields.

💡 Best Practices

✅ Do

  • Use tuple input: ["$score", "$playerId"] to attach context to each top value
  • Combine $max + $maxN when dashboards need peak and top-N together
  • Put $match before $group to shrink groups and avoid memory pressure
  • Use $topN 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 $maxN with $max (array vs single value)
  • Expect null scores to appear in the result—they are filtered out
  • Assume output order on tied equal values—use $topN 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 $maxN

Use these points when building top-N max 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 $topN

Max vs ranked docs.

Choose

❓ Frequently Asked Questions

$maxN returns an array of the N largest input values from each $group bucket. It compares values across all documents in the group and keeps the top N—no $sort stage required.
Inside $group: { topThree: { $maxN: { input: "$score", n: 3 } } }. Both input and n are required. It also works as an aggregation expression and window operator.
$max returns a single highest value. $maxN returns an array of up to N highest values. Use $max for the peak alone; use $maxN for a top-N leaderboard of scores or prices.
$maxN finds the N maximum values by comparison without requiring sortBy. $topN ranks inside $group with sortBy and returns the top N documents. Use $topN when you need a guaranteed sort order on ties.
No. Unlike $firstN and $lastN, $maxN filters out null and missing values. If only three documents have scores and n is 4, you get an array of three elements.
$maxN 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?

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

Continue the Accumulators Series

Build top-N max arrays with $maxN, then learn $mergeObjects for combining document fields.

Next: $mergeObjects →

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