最新下载
热门教程
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
MongoDB如何查询并返回去重后的字段值?
时间:2026-08-30 09:10:49 编辑:袖梨 来源:一聚教程网
distinct()最快但仅支持单字段去重,返回纯数组;字段名须为字符串字面量,嵌套字段点号合法但空值文档被跳过;空字符串、null、undefined视为不同值;需条件过滤或频次统计时应改用$group聚合。
直接用 distinct() 最快,但只支持单字段
如果你只需要一个字段的所有不重复值(比如所有不同的 city),distinct() 是最轻量的选择。它不走聚合管道,服务端开销小、响应快。
- 字段名必须是字符串字面量,不能是变量拼接后未校验的值,否则抛
TypeError: string expected - 嵌套字段如
"user.profile.city"允许用点号,但若某文档中user为null或缺失,该文档会被静默跳过 - 空字符串
""、null、undefined在distinct()中视为不同值;而聚合的$group通常把null和缺失字段归为同一组 - Node.js 驱动返回的是 Promise,且结果是纯数组(如
["bj", "sh"]),不带任何元信息——没计数、没排序、没法过滤
要加条件或统计频次,必须上聚合 $group
一旦你需要“只查 status=active 的用户的城市”或者“每个城市有多少人”,distinct() 就不够用了。这时候得用 aggregate() + $group。
-
$group默认把分组键塞进_id字段,比如{ "_id": "bj" }或{ "_id": { "city": "bj", "country": "cn" } } - 如果后续要统计频次,直接在
$group里加count: { $sum: 1 },别想着先distinct()再对每个值调countDocuments(),性能差好几个数量级 - 想按频次倒序排?加个
$sort: { count: -1 }就行;想筛掉只出现一次的?后面接$match: { count: { $gt: 1 } }
Spring Data MongoDB 返回多字段 DTO,必须手动 $project 解构 _id
当你需要联合去重两个字段(比如 organizationId 和 organizationName),并映射成 Java 的 OrganizationDTO,光用 GroupOperation 会返回空对象——因为默认结构是 { "_id": { "organizationId": "...", "organizationName": "..." } },而 DTO 没有 _id 这个嵌套层级。
- 必须补一个
ProjectionOperation,把_id.organizationId提升为顶层organizationId - 关键操作是
.andExclude("_id"),否则反序列化时 Jackson 会试图把整个_id对象塞进 DTO 的某个字段,导致字段不匹配、值为 null - 如果字段可能为空,
$first比$push更安全;但注意$first不保证取到的是“最早”文档的值,只是组内任意一个非空值
单节点连不上 distinct()?检查连接字符串和驱动版本
报错 Command failed: distinct command is only supported on replica sets and sharded clusters,大概率不是 MongoDB 版本问题,而是客户端配置误导了驱动。
- 确认你用的是 MongoDB 4.2+ 单节点,但连接 URL 里还带着
?replicaSet=rs0——删掉它,单节点也能跑distinct() - 旧版 Node.js 驱动(distinct(),升级驱动比改服务配置更靠谱
- PHP 的
mongodbcollection::distinct()和 Spring 的mongoTemplate.findDistinct()行为一致,但 Spring 的方法不支持多字段,这点容易踩坑
distinct() 和聚合之间反复横跳,最后发现不是少了个 $project,就是连错环境白调半天。