如何用MongoDB聚合管道获取多文档数组字段的去重值合集
结论
这个需求完全可以通过MongoDB原生聚合管道实现,不需要应用层做额外计算,推荐用$facet阶段并行处理两个数组字段,避免多字段$unwind产生笛卡尔积导致的性能浪费。
实现逻辑
- 配置两个独立的聚合分支,分别处理
tags和dim_cm字段,分支间逻辑互不干扰 - 每个分支先通过
$unwind把对应数组拆成单条文档的单个值,再用$group搭配$addToSet自动收集跨文档的去重值 - 最后调整输出结构,和预期格式对齐
聚合代码
假设集合名为items,可直接执行以下聚合语句:
db.items.aggregate([ { $facet: { unique_tags: [ { $unwind: "$tags" }, // 如果需要过滤特定值比如plain,在这里加{ $match: { tags: { $ne: "plain" } } }即可 { $group: { _id: null, values: { $addToSet: "$tags" } } }, { $project: { _id: 0 } } ], unique_dim_cm: [ { $unwind: "$dim_cm" }, { $group: { _id: null, values: { $addToSet: "$dim_cm" } } }, { $project: { _id: 0 } } ] } }, { $project: { "tags去重合集": { $first: "$unique_tags.values" }, "dim_cm去重合集": { $first: "$unique_dim_cm.values" } } } ])
返回结果
执行后返回的结果结构如下:
[ { tags去重合集: ["blank", "red", "plain", "blue"], dim_cm去重合集: [14, 21, 22.85, 30, 10, 15.25] } ]
说明:你给出的预期tags结果里少了示例文档
paper中包含的plain值,如果不需要这个值,按照代码注释里的位置加$match过滤即可。
补充说明
$addToSet操作符本身自带去重特性,不需要额外编写去重逻辑- 如果使用MongoDB 5.2及以上版本,可以在每个分支的
$project前增加排序逻辑,对去重后的数组做排序,示例:{ $addFields: { values: { $sortArray: { input: "$values", sortBy: 1 } } } } - 数据量较大时,
$facet并行处理的性能远高于连续$unwind两个数组再分组的写法,不会产生冗余的笛卡尔积数据。
内容的提问来源于stack exchange,提问作者Peanuts-83
相关产品推荐
相关产品推荐

