MongoDB $bottom Accumulator

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

What You’ll Learn

The $bottom accumulator picks the single lowest-ranked document in each $group bucket using a sortBy specification—ideal for “worst score,” “earliest order,” or “lowest price” reports.

01

One doc per group

Full record at bottom of sort.

02

sortBy required

Defines what “bottom” means.

03

output shape

$$ROOT or selected fields.

04

vs $min

Value only vs whole document.

05

vs $bottomN

One record vs N records.

06

MongoDB 5.2+

Part of $top/$bottom family.

Definition and Usage

$bottom is a MongoDB accumulator used in the $group stage. It sorts documents within each group according to sortBy, then returns the document at the bottom of that ordering (the last one if you sorted ascending, or the minimum rank depending on your sort keys).

💡
Beginner tip

With sortBy: { score: 1 }, ascending order puts the smallest score at the bottom—so $bottom returns the student with the lowest score in each class. Use score: -1 when “bottom” should mean the lowest rank in a descending list.

Choose $bottom when you need identifying fields (name, id, date) from the extreme record. Use $min when you only need the numeric minimum. Need multiple low-ranked rows? Use $bottomN.

📝 Syntax

$bottom requires an object with output and sortBy:

mongosh
{
  $group: {
    _id: <expression>,
    <field>: {
      $bottom: {
        output: <expression> | { <field>: <expression>, ... },
        sortBy: { <field>: <1 | -1>, ... }
      }
    }
  }
}

Syntax Rules

  • output — what to return: "$$ROOT" for the full document, or a projection object.
  • sortBy — required; same format as $sort (1 = ascending, -1 = descending).
  • One document — unlike $bottomN, result is a single object per group, not an array.
  • Ties — when sort keys tie, MongoDB picks one of the tied documents (do not rely on tie order without extra sort fields).
  • Version — available in MongoDB 5.2 and later.
mongosh
db.scores.aggregate([
  {
    $group: {
      _id: "$class",
      lowestScorer: {
        $bottom: {
          output: { name: "$student", score: "$score" },
          sortBy: { score: 1 }
        }
      }
    }
  }
]);

⚡ Quick Reference

QuestionAnswer
Stage$group accumulator
Required keysoutput, sortBy
ReturnsOne document (or projected object) per group
Lowest score patternsortBy: { score: 1 }
Full documentoutput: "$$ROOT"
MongoDB version5.2+
Lowest score
sortBy: { score: 1 }

Ascending → min at bottom

Full doc
output: "$$ROOT"

Entire source document

Projection
output: {
  name: "$student",
  score: "$score"
}

Selected fields only

Tie-break
sortBy: {
  score: 1,
  student: 1
}

Stable ordering

🧰 Parameters

The $bottom object has two required properties:

output Required

Expression or document defining what the accumulator returns. Use "$$ROOT" for the full input document, or build a sub-object with field projections.

output: "$$ROOT"
output: { id: "$_id", score: "$score" }
sortBy Required

Sort specification applied within each group before picking the bottom document. Mirrors $sort syntax with 1 (asc) and -1 (desc).

sortBy: { score: 1 }
sortBy: { date: 1, amount: 1 }
_id Group key

Standard $group bucket key—e.g. "$class" for per-class lowest scorers.

_id: "$department"
empty group Edge case

If no documents fall in a group, that group is not emitted. Pipelines with only empty buckets return an empty result set.

$match before $group

Examples Gallery

Student scores by class—find the lowest scorer per section and compare with $min.

📚 Getting Started

Sample scores and the core $bottom grouping pattern.

Example 1 — Sample scores collection

mongosh
db.scores.insertMany([
  { student: "Alice",   class: "10A", score: 85 },
  { student: "Bob",     class: "10A", score: 72 },
  { student: "Charlie", class: "10A", score: 91 },
  { student: "Diana",   class: "10B", score: 68 },
  { student: "Eve",     class: "10B", score: 88 }
]);

How It Works

Class 10A lowest is Bob (72); class 10B lowest is Diana (68)—clear targets for verifying $bottom output.

Example 2 — Lowest scorer per class

mongosh
db.scores.aggregate([
  {
    $group: {
      _id: "$class",
      lowestScorer: {
        $bottom: {
          output: { name: "$student", score: "$score" },
          sortBy: { score: 1 }
        }
      }
    }
  },
  { $sort: { _id: 1 } }
]);

/* Result:
[
  { _id: "10A", lowestScorer: { name: "Bob", score: 72 } },
  { _id: "10B", lowestScorer: { name: "Diana", score: 68 } }
]
*/

How It Works

Within each class group, MongoDB sorts by ascending score and returns the bottom document’s projected fields.

📈 Practical Patterns

Return full documents, compare accumulators, and handle ties.

Example 3 — Return the full document with $$ROOT

mongosh
db.scores.aggregate([
  {
    $group: {
      _id: "$class",
      lowestRecord: {
        $bottom: {
          output: "$$ROOT",
          sortBy: { score: 1 }
        }
      }
    }
  }
]);

// lowestRecord contains student, class, score, _id fields

How It Works

$$ROOT refers to the current document in the group during accumulation—useful when downstream stages need every field.

Example 4 — $bottom vs $min

mongosh
db.scores.aggregate([
  {
    $group: {
      _id: "$class",
      minScore: { $min: "$score" },
      bottomStudent: {
        $bottom: {
          output: { name: "$student", score: "$score" },
          sortBy: { score: 1 }
        }
      }
    }
  }
]);

/* 10A:
  minScore: 72
  bottomStudent: { name: "Bob", score: 72 }
  — same number, but $bottom also gives you the name */
*/

How It Works

Use both in the same $group when dashboards show the minimum value and the record that achieved it.

Example 5 — Tie-break with secondary sort

When two students share the lowest score, add a secondary key so ranking is predictable:

mongosh
db.scores.aggregate([
  {
    $group: {
      _id: "$class",
      lowestScorer: {
        $bottom: {
          output: { name: "$student", score: "$score" },
          sortBy: { score: 1, student: 1 }
        }
      }
    }
  }
]);

// If Bob and Blake both score 72, student: 1
// puts Blake before Bob — Blake wins the tie

How It Works

Always add tie-breakers (name, timestamp, _id) when business rules require deterministic winners.

🧠 How $bottom Works

1

Documents bucketed

$group assigns each document to a group via _id.

Group
2

Sorted within group

sortBy ranks documents inside each bucket independently.

Sort
3

Bottom document selected

The last document in that sort order becomes the accumulator result.

Pick
=

output returned

The output expression shapes what fields appear in the final object.

📝 Notes

  • $bottom requires MongoDB 5.2+—verify server version before deploying.
  • sortBy is mandatory—there is no default sort order.
  • Result is one document per group, not an array (use $bottomN for many).
  • Ties may pick an arbitrary winner unless you add secondary sortBy keys.
  • On older MongoDB, approximate with $sort + $group + $first patterns (less efficient).
  • Previous topic: $avg. Next: $bottomN.

Conclusion

$bottom answers “which single record is at the low end of my ranking?” inside each group. Define sortBy carefully, project with output, and add tie-breakers when duplicates matter.

Pair with $min for the numeric extreme alone, or move to $bottomN when you need several bottom-ranked documents per bucket.

💡 Best Practices

✅ Do

  • Always specify sortBy explicitly—match your business definition of “bottom”
  • Add secondary sort keys (student, _id) to break ties
  • Use $$ROOT when downstream stages need the full document
  • Put $match before $group to shrink working sets
  • Confirm MongoDB 5.2+ in staging before production rollout

❌ Don’t

  • Confuse $bottom with $bottomN (one doc vs array)
  • Expect $min to return student names—it only returns the minimum value
  • Rely on tie order without extra sortBy fields
  • Use on MongoDB versions before 5.2 without a fallback pipeline
  • Forget that sort direction changes which document is “bottom”

Key Takeaways

Knowledge Unlocked

Five things to remember about $bottom

Use these points when ranking documents inside $group.

5
Core concepts
📦 02

sortBy

Required ranking spec.

Syntax
👤 03

vs $min

Doc vs scalar value.

Compare
📄 04

$$ROOT

Return full record.

Pattern
🔢 05

5.2+

Check server version.

Version

❓ Frequently Asked Questions

$bottom returns one document per $group—the document ranked last according to the sortBy order you specify. It is useful when you need the whole record (name, score, date), not just a single field value.
Inside the $group stage: { lowest: { $bottom: { output: "$$ROOT", sortBy: { score: 1 } } } }. It requires both output and sortBy.
$min returns the smallest value of one field (e.g. the number 72). $bottom returns an entire document—the student or order that sits at the bottom of your sort order.
$bottom returns exactly one bottom-ranked document. $bottomN returns N bottom documents as an array. Use $bottom when you only need the single worst/lowest record.
$bottom was added in MongoDB 5.2 as part of the $top/$bottom accumulator family. Upgrade the server or use $sort + $first/$last patterns on older versions.
sortBy defines ranking within each group—same rules as $sort. Use { score: 1 } for lowest score first (bottom = smallest score), or { date: 1 } for earliest date at the bottom.
Did you know?

$bottom and $top were added together in MongoDB 5.2 to replace fragile $sort + $group + $first recipes for ranked group results. See the official $bottom docs.

Continue the Accumulators Series

Pick the single bottom record with $bottom, then learn $bottomN for multiple ranked results.

Next: $bottomN →

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