MongoDB $sort Stage

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

What You’ll Learn

The $sort stage orders documents in your pipeline—ascending or descending by one or more fields—so top-N lists, leaderboards, and paginated APIs return predictable results.

01

1 / -1

Asc / desc.

02

Multi-key

Tie-breakers.

03

Top-N

With $limit.

04

Pagination

Before $skip.

05

Computed

After $set.

06

Indexes

Performance.

Definition and Usage

$sort is an aggregation stage that rearranges documents by specified field(s). Each sort key uses 1 for ascending order or -1 for descending order. MongoDB compares fields left to right when multiple keys are listed.

💡
Beginner tip

{ $sort: { price: 1 } } = cheapest first.
{ $sort: { price: -1 } } = most expensive first.
{ $sort: { score: -1, name: 1 } } = highest score first; ties sorted A→Z by name.

Use $sort whenever order matters: recent-first feeds, leaderboard rankings, alphabetical directories, and the stable ordering required before $skip and $limit pagination.

📝 Syntax

$sort accepts an object of field names mapped to sort direction:

mongosh
{
  $sort: {
    <field1>: <1 | -1>,
    <field2>: <1 | -1>,
    ...
  }
}

Syntax Rules

  • 1 — ascending (smallest / earliest / A→Z first).
  • -1 — descending (largest / latest / Z→A first).
  • Multiple fields — listed in priority order; later fields break ties from earlier fields.
  • Missing fields — documents missing a sort key are treated as null and sort together.
  • Computed fields — sort on fields added by $set or $addFields in earlier stages.
  • Memory limit — in-memory sorts default to 100 MB; large sorts may need allowDiskUse: true.
mongosh
db.students.aggregate([
  { $sort: { score: -1 } }
])

⚡ Quick Reference

QuestionAnswer
What it doesOrders documents by one or more fields
Ascending{ $sort: { field: 1 } }
Descending{ $sort: { field: -1 } }
Tie-breakerAdd more fields: { score: -1, name: 1 }
Top 5 pattern$sort$limit: 5
Pagination pattern$sort$skip$limit
A→Z
{ $sort: {
  name: 1
}}

Ascending

High first
{ $sort: {
  score: -1
}}

Descending

Multi-key
{ $sort: {
  grade: -1,
  name: 1
}}

Tie-break

Top 3
$sort →
$limit: 3

Leaderboard

🧰 $sort Keys & Directions

Each key in the $sort object is a field path and a direction. Common patterns:

field: 1 Ascending

Low to high numbers, earliest to latest dates, alphabetical names (A→Z).

{ $sort: { price: 1 } }
{ $sort: { createdAt: 1 } }
field: -1 Descending

High to low numbers, newest first, reverse alphabetical (Z→A).

{ $sort: { score: -1 } }
{ $sort: { updatedAt: -1 } }
Multi-field Tie-break

When the first key matches, MongoDB uses the second key, then the third, and so on.

{ $sort: {
  department: 1,
  salary: -1,
  name: 1
}}
Nested path Dot notation

Sort on nested fields using dot notation in the key name.

{ $sort: {
  "address.city": 1,
  "address.zip": 1
}}

Examples Gallery

Students collection—alphabetical sort, score leaderboard, multi-key ranking, sort computed totals, and paginated results with skip and limit.

📚 Getting Started

Eight students across three grades for sorting labs.

Example 1 — Students collection

mongosh
db.students.drop()

db.students.insertMany([
  { name: "Ana",   grade: "10", score: 88, examsTaken: 3 },
  { name: "Ben",   grade: "10", score: 92, examsTaken: 4 },
  { name: "Cara",  grade: "10", score: 92, examsTaken: 3 },
  { name: "Dan",   grade: "11", score: 75, examsTaken: 2 },
  { name: "Eli",   grade: "11", score: 81, examsTaken: 5 },
  { name: "Faye",  grade: "11", score: 95, examsTaken: 4 },
  { name: "Gabe",  grade: "12", score: 70, examsTaken: 3 },
  { name: "Hana",  grade: "12", score: 84, examsTaken: 4 }
])

How It Works

Eight students with duplicate scores (Ben and Cara both 92) make multi-key tie-breaker sorting easy to demonstrate.

Example 2 — Sort names A→Z (ascending)

mongosh
db.students.aggregate([
  { $sort: { name: 1 } },
  {
    $project: {
      _id: 0,
      name: 1,
      grade: 1,
      score: 1
    }
  }
])

// name: 1 → Ana, Ben, Cara, Dan, Eli, Faye, Gabe, Hana
// Useful for directories and dropdown lists

How It Works

The simplest sort: one field, direction 1. Strings sort lexicographically—fine for short names; for case-insensitive sort, normalize with $set first.

Example 3 — Top 3 scores (descending + $limit)

mongosh
db.students.aggregate([
  { $sort: { score: -1 } },
  { $limit: 3 },
  {
    $project: {
      _id: 0,
      name: 1,
      score: 1
    }
  }
])

// score: -1 → highest first
// Faye 95, Ben 92, Cara 92 — but order between Ben/Cara not guaranteed
// (same score, no tie-breaker yet)

How It Works

Leaderboard pattern: $sort descending then $limit. When scores tie, add a second sort key for deterministic ranking.

📈 Practical Patterns

Tie-breakers, computed averages, and paginated grade lists.

Example 4 — Multi-key sort (score desc, name asc)

mongosh
db.students.aggregate([
  { $sort: { score: -1, name: 1 } },
  {
    $project: {
      _id: 0,
      name: 1,
      score: 1,
      rankNote: {
        $concat: [
          "Score ",
          { $toString: "$score" },
          " — ",
          "$name"
        ]
      }
    }
  }
])

// Faye 95 first
// Ben 92 before Cara 92 (alphabetical tie-break)
// Gabe 70 last

How It Works

Multi-key $sort mirrors SQL ORDER BY score DESC, name ASC. Always add tie-breakers when equal values would confuse users or pagination.

Example 5 — Grade 11 leaderboard with $set, $sort, $skip, $limit

mongosh
const page = 1
const pageSize = 2
const skip = (page - 1) * pageSize

db.students.aggregate([
  { $match: { grade: "11" } },
  {
    $set: {
      avgPerExam: {
        $divide: ["$score", "$examsTaken"]
      }
    }
  },
  { $sort: { avgPerExam: -1, name: 1 } },
  { $skip: skip },
  { $limit: pageSize },
  {
    $project: {
      _id: 0,
      name: 1,
      grade: 1,
      score: 1,
      examsTaken: 1,
      avgPerExam: 1
    }
  }
])

// Grade 11: Dan, Eli, Faye
// avgPerExam: Faye 23.75, Eli 16.2, Dan 37.5
// Sorted: Dan (37.5), Faye (23.75), Eli (16.2)
// Page 1 limit 2: Dan, Faye
// Page 2 skip 2: Eli

How It Works

Production pipelines combine filter, computed fields, sort, and pagination. Sort must precede skip/limit so each page shows the correct slice of the ranked list.

🧠 How $sort Works

1

Documents arrive

Input from collection or prior stages ($match, $set, etc.).

Input
2

Sort plan chosen

MongoDB uses an index if sort keys match, otherwise performs an in-memory (or disk-spill) sort.

Plan
3

Order applied

Documents emit in sorted order—first key primary, additional keys break ties.

Reorder
=

Ordered stream

Downstream stages like $skip, $limit, and $group receive predictably ordered documents.

📝 Notes

  • Use 1 and -1 only—other numbers are invalid sort directions.
  • Place $sort before $skip and $limit for ranked pagination.
  • Add tie-breaker keys when equal values would produce unstable order.
  • Large in-memory sorts hit the 100 MB limit—use indexes or allowDiskUse: true.
  • $sort on computed fields requires $set or $addFields in an earlier stage.
  • Previous topic: $skip. Next: $sortByCount.

Conclusion

$sort defines pipeline order: ascending with 1, descending with -1, multi-key for tie-breakers, and always before skip/limit when pages must be stable.

Next: $sortByCount—a specialized stage that groups, counts, and sorts category frequencies in one step.

💡 Best Practices

✅ Do

  • Create indexes matching your most common $sort keys
  • Add a unique tie-breaker (e.g. _id or name) for stable pages
  • Combine $sort + $limit for top-N leaderboards
  • Filter with $match before sorting large collections
  • Sort computed fields after $set when ranking derived metrics

❌ Don’t

  • Rely on natural collection order—always sort explicitly
  • Put $skip before $sort when order matters
  • Sort huge result sets without indexes on busy production clusters
  • Confuse $sort with $sortByCount for general ordering
  • Forget allowDiskUse when sorts exceed memory on big batches

Key Takeaways

Knowledge Unlocked

Five things to remember about $sort

Use these points whenever pipeline order matters.

5
Core concepts
🔗 02

Multi-key

Tie-break.

Pattern
🏆 03

Top-N

+ $limit.

Rank
📄 04

Before skip

Stable pages.

Pagination
05

Index match

Fast sort.

Perf

❓ Frequently Asked Questions

$sort reorders documents in the aggregation pipeline by one or more fields. Use 1 for ascending (A→Z, low→high) and -1 for descending (Z→A, high→low). Sorted output flows to stages like $skip, $limit, or $group.
{ $sort: { fieldName: 1 } } sorts ascending; { $sort: { fieldName: -1 } } sorts descending. List multiple fields for tie-breakers: { $sort: { score: -1, name: 1 } }.
Yes, when you need meaningful pagination or top-N lists. Pattern: $match → $sort → $skip → $limit. Without $sort first, skip/limit operate on arbitrary order.
Yes. Add the field with $set or $addFields, then $sort on that computed field—e.g. lineTotal from $multiply before sorting by revenue.
When $sort is early in the pipeline and matches an index key order, MongoDB can use the index and avoid an in-memory sort. Otherwise it performs an in-memory sort subject to the 100 MB limit unless allowDiskUse is enabled.
$sort orders full documents by field values. $sortByCount groups by a field, counts each group, and returns sorted count summaries—it is a shortcut for group-plus-sort on counts, not general document sorting.
Did you know?

When $sort is the first stage and its keys match a collection index, MongoDB can return results in index order without a separate in-memory sort—often the biggest performance win for paginated APIs. Run explain() on your pipeline to see whether the plan says IXSCAN with no SORT stage. See the official $sort docs.

Continue the Stages Series

Order with $sort, then summarize frequencies with $sortByCount.

Next: $sortByCount →

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