如何在MongoDB聚合中基于flagField:true去除用户半重复文档
问题:基于flagField:true去重用户的半重复文档
原始集合数据
[ { "userId": 1, "flagField": false, "extraField": "1" }, { "userId": 1, "flagField": true, "extraField": "2" }, { "userId": 1, "flagField": true, "extraField": "3" }, { "userId": 1, "flagField": false, "extraField": "4" }, { "userId": 2, "flagField": true, "extraField": "1" } ]
期望结果
[ { "userId": 1, "flagField": true, "extraField": "2" }, { "userId": 2, "flagField": true, "extraField": "1" } ]
需求说明
需要筛选出flagField: true的文档,并且对同一userId只保留完整的原始文档(所有字段来自同一条原始记录),同一用户有多条符合条件的文档时,任选其一即可。
解决方案
方法1:$match + $group 组合
先过滤出符合条件的文档,再按userId分组,直接保留完整原始文档:
db.collection.aggregate([ // 第一步:筛选flagField为true的文档 { $match: { flagField: true } }, // 第二步:按userId分组,取每组第一个完整文档(换$last可取最后一个) { $group: { _id: "$userId", doc: { $first: "$$ROOT" } } }, // 第三步:把完整文档作为根文档输出 { $replaceRoot: { newRoot: "$doc" } } ])
$$ROOT代表当前整条原始文档,$first: "$$ROOT"会保留分组后每组的第一条完整记录,满足“所有字段来自同一原始文档”的要求。
方法2:$setWindowFields(支持自定义排序后选文档)
如果需要先对每组内的文档排序(比如按extraField排序)再选取,可用窗口函数实现:
db.collection.aggregate([ { $match: { flagField: true } }, { $setWindowFields: { partitionBy: "$userId", sortBy: { extraField: 1 }, // 按extraField升序排序,可自定义规则 output: { rowNumber: { $rowNumber: {} } } } }, { $match: { rowNumber: 1 } }, // 只保留每组的第一条文档 { $unset: "rowNumber" } // 移除临时添加的行号字段 ])
这种方式可以先对分组内的文档排序,再选取指定位置的完整文档,灵活性更高。
内容的提问来源于stack exchange,提问作者Steven Pauk
相关产品推荐
相关产品推荐

