MongoDB查询集合中三字段重复文档(排除Null值)
找出MongoDB集合中指定字段重复的文档(排除Null值)
针对你需要从包含1000+文档的集合中,筛选出fields1、fields2、fields3字段值完全重复(且排除任一字段为Null的文档),并返回每组重复文档中的任意一条(方便后续删除重复数据)的需求,我整理了一个精准的MongoDB聚合查询方案:
db.yourCollectionName.aggregate([ // 第一步:过滤掉任一指定字段为Null的文档 { $match: { fields1: { $ne: null }, fields2: { $ne: null }, fields3: { $ne: null } } }, // 第二步:按指定字段分组,统计每组的文档数量,同时保留组内所有文档 { $group: { _id: { fields1: "$fields1", fields2: "$fields2", fields3: "$fields3" }, count: { $sum: 1 }, docs: { $push: "$$ROOT" } } }, // 第三步:只保留重复次数大于1的分组 { $match: { count: { $gt: 1 } } }, // 第四步:展开每组的文档列表 { $unwind: "$docs" }, // 第五步:重新分组,为筛选重复项做准备 { $group: { _id: "$_id", docs: { $push: "$docs" }, count: { $first: "$count" } } }, // 第六步:截取每组除第一个外的重复文档(可按需调整取第一个) { $project: { duplicateDocs: { $slice: ["$docs", 1, { $subtract: ["$count", 1] }] } } }, // 第七步:展开重复文档列表 { $unwind: "$duplicateDocs" }, // 第八步:恢复文档的原始结构 { $replaceRoot: { newRoot: "$duplicateDocs" } } ])
方案细节解释:
- $match(第一步):严格过滤掉
fields1、fields2、fields3任一为Null的文档,确保后续处理的都是有效值。 - $group(第二步):以三个字段的组合为分组依据,统计每组的文档数量
count,并用$push把组内所有原始文档存入docs数组。 - $match(第三步):只保留重复次数大于1的分组,直接排除唯一文档(比如示例中的
_id:5)。 - $slice(第六步):这里用
$slice截取每组文档数组中从第2个元素开始的所有文档——如果你的需求是保留每组的第一个重复项,改成$slice: ["$docs", 0, 1]即可灵活调整。 - $replaceRoot(第八步):把筛选出的重复文档恢复成原始的文档结构,方便后续的删除或其他操作。
针对你的示例数据:
运行上述查询后,会精准返回:
[ {_id:2,fields1:'a',fields2:1,fields3:'z'}, {_id:4,fields1:'f',fields2:2,fields3:'g'} ]
完全匹配你的期望结果。如果需要批量删除这些重复文档,可以直接提取结果中的_id列表,结合deleteMany操作完成清理。
内容的提问来源于stack exchange,提问作者Darkmagister
相关产品推荐
相关产品推荐

