$sortByCount专用于统计高频值,仅支持单表达式输入、固定输出结构(_id和count),不支持条件过滤或多字段聚合,大集合需配置allowDiskUse以防内存溢出。

$sortByCount适合统计高频值,不是通用分组工具
它专为“找出出现最多的几个值”设计,比如热门标签、高频用户ID、最常访问的页面路径。如果你需要带条件过滤、多字段聚合或自定义计数逻辑,$sortByCount反而会限制你——它内部硬编码了$sum: 1和$sort: { count: -1 },没法改。
必须用字段路径或表达式,不能写对象字面量
常见错误是直接传一个对象进去,比如{"category": "$sales.category"},这会报错“invalid expression”。$sortByCount只接受单个表达式,不支持结构化输出。
- ✅ 正确:
{"$sortByCount": "$promotionevents.eventname"} - ✅ 正确(嵌套字段):
{"$sortByCount": "$sales.salesbycategory.categoryname"} - ✅ 正确(拼接):
{"$sortByCount": {"$concat": ["$name", "-", "$borough"]}} - ❌ 错误:
{"$sortByCount": {"event": "$promotionevents.eventname"}}
大集合上容易触发内存溢出,得主动配allowDiskUse
当去重后的分组数特别多(比如日志里有上百万种URL),或者单个分组文档极多时,$sortByCount可能吃光100MB内存限额,直接报错Exceeded memory limit。
- MongoDB 6.0+ 默认允许落盘,但旧版本必须显式加
{ allowDiskUse: true } - Atlas用户要注意:临时文件会触发自动扩容,可能意外涨费用
- 更稳的做法是先
$match缩小范围,再$sortByCount,比硬扛全量数据安全得多
输出结构固定,_id就是分组值,count就是数量
它不给你自由选字段名的机会,也不支持额外计算字段。比如你想同时输出“占比”,就得在后面接$addFields阶段手动算:{"$addFields": {"percentage": {"$divide": ["$count", "$total"]}}}。
- 输入文档:
{"_id": 1, "tag": "wine"}→{"_id": "wine", "count": 42} - 没法把
_id改成top_tag,也没法让count变成frequency - 如果要排序后取Top N,必须跟
$limit,不能靠$sortByCount自己截断
真正难处理的不是语法,而是它隐含的假设:你只关心“谁最多”,且愿意接受它的输出契约。一旦需求变复杂,立刻得切回$group+$sort组合。











