如何在MongoDB中基于多个数组字段删除重复文档
MongoDB邮件文档去重解决方案
前置说明
你给出的是MongoDB存储的邮件结构文档,可通过聚合查询实现基于指定字段的重复判定与去重,以下是具体操作步骤:
步骤1:先查询重复文档做验证
先执行以下聚合语句确认重复数据,避免误删:
db.your_collection_name.aggregate([ // 按你指定的5个字段分组,完全匹配才会归为同一组 { $group: { _id: { internetMessageId: "$internetMessageId", from: "$from", toRecipients: "$toRecipients", ccRecipients: "$ccRecipients", bccRecipients: "$bccRecipients" }, // 统计每组重复数量 count: { $sum: 1 }, // 收集每组所有文档的_id,方便后续删除 docIds: { $push: "$_id" } } }, // 只筛选出有重复的组(数量>1) { $match: { count: { $gt: 1 } } } ])
注意:默认数组顺序不同会被判定为不同组,如果你认为只要收件人/抄送人邮箱集合一致、不管顺序都算同一封邮件,需要在分组前加
$project阶段,对数组内的邮箱地址做排序后再分组。
步骤2:删除重复文档,仅保留一份
以下示例保留每组中最早插入的文档(ObjectId自带时间戳,取最小的_id保留),如需保留最新文档可把$min替换为$max:
db.your_collection_name.aggregate([ { $group: { _id: { internetMessageId: "$internetMessageId", from: "$from", toRecipients: "$toRecipients", ccRecipients: "$ccRecipients", bccRecipients: "$bccRecipients" }, // 保留最早的文档_id keepId: { $min: "$_id" }, // 收集所有文档_id allIds: { $push: "$_id" } } }, { $project: { // 过滤掉要保留的_id,剩下的就是要删除的 deleteIds: { $setDifference: [ "$allIds", [ "$keepId" ] ] } } } ]).forEach(doc => { // 批量删除重复文档 db.your_collection_name.deleteMany({ _id: { $in: doc.deleteIds } }) })
步骤3:长期避免重复写入
去重完成后,可以建立复合唯一索引,后续写入重复数据会直接报错拒绝写入,从根源避免重复:
db.your_collection_name.createIndex( { internetMessageId: 1, from: 1, toRecipients: 1, ccRecipients: 1, bccRecipients: 1 }, { unique: true } )
注意:建索引前必须确保现有数据没有重复,否则索引会创建失败。
内容的提问来源于stack exchange,提问作者Hej Ja
相关产品推荐
相关产品推荐

