MongoDB $top Accumulator

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

What Is $top?

$top is a MongoDB accumulator for the $group stage. It ranks documents in each group with sortBy, then returns the first-ranked document shaped by output—ideal for the highest scorer or most recent order when you need more than a single number.

Remember
$top = first document after sortBy (per group)

sortBy → ranking (same style as $sort)
output → shape of the returned value

vs $max  → one field's max number vs a full ranked record
vs $topN → one document vs an array of up to N
MongoDB 5.2+
UsePrefer
Single best ranked record per group$top
Top-k ranked list$topN
Largest number only (no identity fields)$max
Single worst / lowest-ranked record$bottom

How to Use $top in MongoDB

Two keys drive every $top call inside $group.

  1. Put $top inside $group on an output field.
  2. Set sortBy so “top” matches your ranking (for highest scores: { score: -1 }).
  3. Set output to the fields (or $$ROOT) you want from that winning document.
  4. Choose _id for the group key (game, category, or null for one group).
KeyRequired?Role
sortByYesSort spec like $sort (1 / -1)
outputYesProjection, field path, array of fields, or $$ROOT

Pseudocode

Pseudocode
for each group:
    ranked = sort(documents, sortBy)
    winner = first document in ranked
    result = output(winner)
    emit { _id: groupKey, field: result }

Cheat Sheet

Keep these facts handy while writing a top-ranked report.

TopicDetail
Stage$group only (as an accumulator)
Minimal keyssortBy, output
Highest scoresortBy: { score: -1 }
vs $maxNumber vs shaped / full document
vs $topNOne document vs array of up to N
VersionMongoDB 5.2+
Sample checkG1 scores 99, 33, 31, 1 → top = PlayerC 99

Live Preview

Watch $top pick the highest score after a descending sortBy. Sample: G1 (99, 33, 31, 1) and G2 (80, 66, 14, 10).

Simulates sortBy: { score: -1 } then taking the first document (same idea as the mongosh examples below).

Result
G1 sort desc: 99 → 33 → 31 → 1
$top → ["PlayerC", 99]

G2 sort desc: 80 → 66 → 14 → 10
$top → ["PlayerD", 80]

[
  { _id: "G1", winner: ["PlayerC", 99] },
  { _id: "G2", winner: ["PlayerD", 80] }
]

Worked Walkthrough — Top Score in Game G1

Four G1 scores. Descending sort puts 99 first—so $top keeps PlayerC.

Calculation
Documents (game G1):
  PlayerA 31, PlayerB 33, PlayerC 99, PlayerD 1

sortBy: { score: -1 }  (high → low)
  99 → 33 → 31 → 1

$top keeps the first document
  PlayerC, score 99

output: ["$playerId", "$score"]
  ["PlayerC", 99]

Note: "top" means start of the sorted list —
match sortBy to your definition of best.

MongoDB Examples

We use a tiny gamescores collection. First we find the top scorer in one game, then per game, then compare with $max. Run these in mongosh after inserting the sample data once.

Example 1 — Sample Data

Two games, four players each. Notice G1 has a clear high score (99)—perfect for checking $top.

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 the Data Is Stored in MongoDB

After the insert, MongoDB keeps 8 documents in gamescores. Run find() to see them:

mongosh
db.gamescores.find()

Read each document like this:

Field in MongoDBMeaningExample
playerIdWho played"PlayerC"
gameIdWhich game"G1"
scorePoints scored99
Picture
G1 scores: 99, 33, 31, 1
G2 scores: 80, 66, 14, 10

Next: $top picks the highest score per game.

How It Works

  1. Insert once. The sample command adds 8 documents to gamescores.
  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 $top in the next examples.

Example 2 — Top Score in One Game

Goal: for game G1 only, return the highest scorer as a [playerId, score] pair.

mongosh
db.gamescores.aggregate([
  { $match: { gameId: "G1" } },
  {
    $group: {
      _id: "$gameId",
      winner: {
        $top: {
          sortBy: { score: -1 },
          output: ["$playerId", "$score"]
        }
      }
    }
  }
]);

How It Works

  1. Filter first. $match keeps only G1 documents so the group is small and clear.
  2. One bucket. _id: "$gameId" makes a single group labeled "G1".
  3. Rank high to low. sortBy: { score: -1 } orders scores as 99 → 33 → 31 → 1.
  4. Keep the leader. $top takes the first document: PlayerC with 99.
  5. Shape the result. output: ["$playerId", "$score"] returns a two-value array instead of the whole document.

Example 3 — Top Score per Game

Goal: same top-score rule for every gameId, with a projection object instead of tuples.

mongosh
db.gamescores.aggregate([
  {
    $group: {
      _id: "$gameId",
      winner: {
        $top: {
          sortBy: { score: -1 },
          output: { player: "$playerId", score: "$score" }
        }
      }
    }
  },
  { $sort: { _id: 1 } }
]);

How It Works

  1. Split by game. Each distinct gameId gets its own group and its own top document.
  2. Same ranking rule. Descending score still means “highest at the top” in every group.
  3. Friendly objects. output: { player, score } is easier to read in APIs than nested arrays.
  4. Stable report order. Final $sort on _id lists G1 before G2 (group order from $group alone is not guaranteed).

Example 4 — $top vs $max

Same G1 filter: $max gives the number 99; $top gives the player who scored it.

mongosh
db.gamescores.aggregate([
  { $match: { gameId: "G1" } },
  {
    $group: {
      _id: "$gameId",
      maxScore: { $max: "$score" },
      winner: {
        $top: {
          sortBy: { score: -1 },
          output: ["$playerId", "$score"]
        }
      }
    }
  }
]);

How It Works

  1. $max is a number. It compares the score field alone and returns 99.
  2. $top is a record. It ranks documents and returns the shaped winner—PlayerC with 99.
  3. Pick by need. Use $max for a single numeric peak; use $top when identity fields matter.
  4. Need several winners? Switch to $topN for an array of top-k documents.

Edge Cases & Pitfalls

Check these before shipping a top-ranked report.

sortBy

“Top” follows sortBy

Highest scores need descending sortBy. Ascending score makes the lowest value sit at the top.

null

Nulls are kept

Missing fields become null and are not filtered out. With ascending numeric sort they can win the top slot.

ties

Break ties explicitly

Equal scores can swap places. Add a secondary key, e.g. sortBy: { score: -1, playerId: 1 }.

version

Needs MongoDB 5.2+

Older servers reject $top. Confirm version before deploying.

Performance Notes

ApproachCostBest for
$topIn-group ranking; keeps one docBest record without a prior global sort
$maxNative field comparisonLargest number only
$sort + $firstExtra sort stageLegacy workaround before 5.2

Prefer $max when you only need a number. Filter early with $match when you only need one game or category. Large groups are still subject to the aggregation memory limit (about 100 MB per group).

Key Takeaways

  • Role: first-ranked document inside each $group bucket.
  • Keys: always set sortBy and output.
  • Highest scores: use sortBy: { score: -1 }.
  • vs $max / $topN: number vs one record vs array of N.

One line: $top returns the first document after sortBy—set ranking carefully, then shape the winner with output.

Frequently Asked Questions

$top returns one document per $group—the document ranked first according to the sortBy order you specify. Use it when you need the whole record (name, score, date), not just a single field value.
Inside $group: { winner: { $top: { sortBy: { score: -1 }, output: { player: "$playerId", score: "$score" } } } }. Both sortBy and output are required.
$max returns the largest value of one field (for example, the number 99). $top returns a shaped document—the player or order that sits at the top of your sort order.
$top returns exactly one top-ranked document. $topN returns up to N top documents as an array. Use $top when you only need the single best record per group.
sortBy defines ranking within each group—same rules as $sort. Use { score: -1 } for highest score first, or { date: -1 } for the most recent document at the top.
$top was added in MongoDB 5.2 alongside $bottom, $topN, and $bottomN. On older servers, approximate with $sort + $first patterns.

Next: $topN

Return the top N ranked documents per group as an array.

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