首页/数据/NoSQL 速查/聚合 $count 简单计数
MongoDB99 条

聚合 $count 简单计数

$count 是 $group + $sum:1 的语法糖:把输入文档数写入指定字段;常与 $match 组合做条件计数。

NoSQL 速查数据更新于 2026-10-13

是什么

$count 是聚合管道里的计数阶段,语法就一句 { $count: "字段名" },语义等价于 { $group: { _id: null, 字段名: { $sum: 1 } } } 再加一次投影。它的价值在于能挂在 $match、$unwind、$lookup 之后,统计过滤或展开后的文档数,而单独的 count 命令做不到这一点。

基本信息

语法{ $count: "字段名" }
等价写法$group 按 _id: null 分组并 $sum: 1
输出单个文档,只含指定字段
位置常作为管道末段:之后的阶段拿到的只有一条计数文档
兄弟方法countDocuments(带条件)、estimatedDocumentCount(不带条件,走元数据估算)

典型使用场景

  • 条件计数:统计状态为 paid 的订单数,比先拉到客户端再 length 高效得多
  • 展开后计数:$unwind 数组字段后统计总元素个数,用于核对一对多数据量
  • 关联后计数:$lookup 之后统计有关联记录的文档数,排查悬空引用
  • 去重后计数:先 $group 按业务主键去重,再用 $count 得到去重数量
  • 质量巡检:统计空值或异常字段的条数,作为数据质量指标

计数示例

计数示例
db.orders.aggregate([
  { $match: { status: "paid" } },       # 先用索引友好的条件缩小范围
  { $count: "paidOrders" }              # 输出单个文档 { paidOrders: N }
])

db.orders.aggregate([                    # 展开数组后统计元素总数
  { $match: { status: "paid" } },
  { $unwind: "$items" },
  { $count: "itemCount" }
])

db.orders.countDocuments({ status: "paid" })   # 单纯条件计数,走查询引擎更快
db.orders.estimatedDocumentCount()             # 估算总量,读元数据,不接条件

三种计数方式对比

方式能否带条件代价适用
$count 阶段可以,配合前序阶段按管道实际扫描量展开、关联、去重后的计数
countDocuments可以走查询与索引单纯条件计数
estimatedDocumentCount不可以读元数据,最快总量概览、监控看板
旧版 count()可以已废弃迁移到上面两种
estimatedDocumentCount 读的是集合元数据,不扫描数据,因此在大集合上毫秒级返回;代价是异常关闭后可能有偏差,需要精确值时不能用它。
在分片集群上带条件的计数要向各分片分发并汇总,代价随分片数增加;把高频计数做成定时落库的汇总表,比每次实时统计更稳妥。

易错点

  • 输出字段名写成带点号的路径或非法字符:写进文档时会报错,习惯用 total、paidOrders 这类简单名称
  • 用 $count 做高频实时统计:每次都要扫过匹配的文档,压力随数据增长,应改为汇总表或缓存
  • 把 estimatedDocumentCount 的结果当精确值:它读元数据估算,数据变动和异常关闭都会带来偏差
  • 在 $count 之后再接 $group 之类的阶段:计数结果只有一条文档、一个字段,后续阶段几乎没有可用信息

数据来源与参考

  • MongoDB Manual: $count
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌