MongoDB $sortByCount Stage

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

What Is $sortByCount?

$sortByCount is a MongoDB aggregation stage that groups documents by an expression, counts each group, and returns the groups sorted by count descending (most common first).

Remember
$sortByCount = group + count + sort(count desc)

{ $sortByCount: "$category" }

output each group as:
  { _id: <value>, count: <N> }

always highest count first
same as:
  $group { _id, count: { $sum: 1 } }
  then $sort { count: -1 }
UsePrefer
Frequency ranking (top categories)$sortByCount
Reorder full documents$sort
Custom group + sort keys$group + $sort

How to Use $sortByCount in MongoDB

Pick the field (or expression) to group on, then let the stage count and rank.

  1. Optionally filter first with $match.
  2. Pass a field path such as "$category" to $sortByCount.
  3. Read each result as { _id, count }, already ranked high → low.
  4. For array tags, $unwind first, then $sortByCount.
PieceRequired?Role
ExpressionYesWhat to group by (often "$field")
Output _id—The group value
Output count—How many docs in that group

Pseudocode

Pseudocode
counts = {}
for each document:
    key = evaluate(expression)
    counts[key] = counts[key] + 1

emit groups as { _id: key, count: N }
sort by count descending

Cheat Sheet

Keep these facts handy while ranking frequencies in pipelines.

TopicDetail
TypeAggregation stage
Syntax{ $sortByCount: <expression> }
Output shape{ _id, count }
Sort orderCount descending only
Equivalent$group + $sort: { count: -1 }
Arrays$unwind first for per-tag counts
Samplebooks 3 · stationery 2 · toys 1

Live Preview

Count product categories and see the ranked { _id, count } list.

Simulates { $sortByCount: "$category" } (highest count first).

Result
[
  { _id: "books", count: 3 },
  { _id: "stationery", count: 2 },
  { _id: "toys", count: 1 }
]

Worked Walkthrough — Category Frequency

Six products sit in a shop. We count how often each category appears and rank the busiest first.

Calculation
categories:
  books, books, books,
  stationery, stationery,
  toys

counts:
  books      → 3
  stationery → 2
  toys       → 1

$sortByCount →
  { _id: "books", count: 3 }
  { _id: "stationery", count: 2 }
  { _id: "toys", count: 1 }

MongoDB Examples

We use six products. First insert them, then run $sortByCount, then show the equivalent $group + $sort pipeline. Run these in mongosh after inserting the sample data once.

Example 1 — Sample Data

Imagine six products across books, stationery, and toys. We save them in a collection named products.

mongosh
db.products.insertMany([
  { _id: 1, name: "Notebook", category: "stationery" },
  { _id: 2, name: "Pencil", category: "stationery" },
  { _id: 3, name: "Math Book", category: "books" },
  { _id: 4, name: "Story Book", category: "books" },
  { _id: 5, name: "Atlas", category: "books" },
  { _id: 6, name: "Yo-Yo", category: "toys" }
]);

How the Data Is Stored in MongoDB

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

mongosh
db.products.find()

Tally by category:

categoryHow many
books3
stationery2
toys1
Picture
books ●●●        (3)
stationery ●●    (2)
toys ●           (1)

$sortByCount ranks ●●● first

How It Works

  1. Insert once. insertMany adds six product documents.
  2. Keep a category field. That is what we will group on.
  3. find() shows all rows. Ranking comes in Example 2.

Example 2 — $sortByCount

Goal: count products per category and list the busiest categories first.

mongosh
db.products.aggregate([
  { $sortByCount: "$category" }
]);

How It Works

  1. Group by category. Each distinct category becomes an _id.
  2. Count documents. Books get 3, stationery 2, toys 1.
  3. Sort by count. Highest frequency appears first automatically.

Example 3 — $group + $sort Equivalent

Same result written as two stages—useful when you need extra accumulators or a different sort.

mongosh
db.products.aggregate([
  {
    $group: {
      _id: "$category",
      count: { $sum: 1 }
    }
  },
  { $sort: { count: -1 } }
]);

How It Works

  1. $group. Builds { _id, count } with $sum: 1.
  2. $sort. { count: -1 } ranks high → low.
  3. Same as $sortByCount. Prefer the short stage for plain frequency rankings.

Edge Cases & Pitfalls

Check these before using $sortByCount for production reports.

order

Always descending count

You cannot flip the sort inside $sortByCount. For ascending counts, use $group + $sort.

shape

Documents become summaries

Output is { _id, count }, not the original products. Keep a copy of the docs earlier if you still need them.

array

Arrays need $unwind

Grouping on an array field treats the whole array as one value. Unwind first for per-element frequencies.

null

Missing fields group as null

Documents without the field land in _id: null. Filter them with $match if that bucket is noise.

Performance Notes

ApproachCostBest for
$match then $sortByCountFewer docs groupedLarge collections
$sortByCount aloneFull scan + groupSmall / already filtered sets
$group + custom $sortSimilar + flexibilityExtra accumulators / asc sort

Grouping reads every document that reaches the stage. Filter early with $match, and add $limit after ranking when you only need the top N.

Key Takeaways

  • Role: group, count, rank by frequency.
  • Output: { _id, count }, highest first.
  • Shortcut: same as $group + $sort count -1.
  • Sample: books 3 → stationery 2 → toys 1.

One line: $sortByCount answers “which values show up most often?”

Frequently Asked Questions

$sortByCount groups documents by an expression (usually a field), counts how many documents fall into each group, and returns those groups sorted by count from highest to lowest. Each result looks like { _id: value, count: N }.
Use { $sortByCount: <expression> }. Most often that expression is a field path such as "$category". Example: { $sortByCount: "$category" }.
$sort reorders full documents. $sortByCount aggregates first—it collapses many documents into frequency summaries for one grouping expression.
Two stages: { $group: { _id: "$category", count: { $sum: 1 } } } followed by { $sort: { count: -1 } }. $sortByCount is the short form of that pair.
Not on the array as a whole. $unwind the array first so each tag is its own document, then run { $sortByCount: "$tags" }.
No. It always sorts by count descending. For ascending counts or other sort keys, use $group plus $sort yourself.

Next: $unset

Drop fields you no longer need from aggregation documents.

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