首页/数据/NoSQL 速查/distinct 去重取值
MongoDB99 条

distinct 去重取值

返回字段的全部去重值数组;支持加查询条件与嵌套路径,结果受 BSON 16MB 限制。

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

distinct 是什么

distinct 返回集合中某个字段的全部去重值,结果是一个数组。它接受可选的查询条件参数,字段路径用点号表示嵌套层级,遇到数组会自动展开后再去重。执行方式分两类:字段上存在可用索引且条件能走索引时按索引扫描,否则退化为全集合扫描。结果必须装在一个 BSON 文档里返回,因此受 16MB 上限约束,取值特别多时会直接报错而不是被截断。

基本信息

语法db.collection.distinct(field, query)
返回去重后的值数组
索引利用字段有序且条件可索引时避免扫全集合
结果上限单个 BSON 文档 16MB,超出直接报错
字段路径支持 "a.b" 嵌套与数组元素展开
所属系统MongoDB 全版本,mongosh 与各语言驱动均可用

典型使用场景

  • 取枚举值:把状态、类型这类低基数字段的全部取值拉出来做筛选下拉框
  • 数据体检:确认某字段有没有出现不该有的脏值或拼写变体
  • 校验建模:看清标签类字段的真实取值范围,再决定要不要改成枚举
  • 小范围对账:核对两个集合在某个字段上的取值集合是否一致
  • 替代分组:值不多时用 distinct 比写聚合管道更省事

常见写法

常见写法
db.orders.distinct("status")                      // 全部去重状态

db.orders.distinct("sku", { status: "paid" })     // 只统计已支付订单的商品

db.orders.distinct("items.sku")                    // 数组字段展开后去重

db.orders.distinct("status", {                      // 限定时间范围,减少扫描量
  ts: { $gte: ISODate("2026-01-01T00:00:00Z") }
})

db.runCommand({ distinct: "orders", key: "status" })  // 驱动层可用 runCommand 形式

参数与限制读法

项含义注意
field要统计的字段路径点号访问嵌套,数组会自动展开
query过滤条件能用索引就快,否则全集合扫描
返回值去重后的值列表形态是数组,直接给前端很方便
16MB 上限结果文档大小限制超限报错而不是返回部分结果
null 项字段缺失的文档值缺失时结果里会出现 null
对高基数字段(用户 ID、订单号)做 distinct 会返回巨大数组,既占内存也容易撞 16MB 上限。这类需求应改成聚合 $group,按值统计条数,只取需要的部分。
distinct 会读取全部匹配文档,在没有合适索引的大集合上是重操作,线上业务高峰执行容易拉高 IO 与响应时间。

易错点

  • 结果超过 16MB 会直接报错(不是分页截断),大结果要用聚合分桶输出
  • 对数组字段做 distinct 得到的是展开后的元素值,与 find 返回的原始形态不一致,接口层要做转换
  • 字段在部分文档中缺失时结果里会多出一个 null,业务代码需要显式处理这一项
  • 在分片集合上不带分片键条件执行 distinct 会打到所有分片,整体延迟取决于最慢的那个分片

数据来源与参考

  • MongoDB Manual: db.collection.distinct()
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌