MongoDB集合中大小写敏感重复文档的移除方案问询
解决MongoDB标题大小写重复且保留原格式的去重方案
你的核心需求是:同一authorId和year下,仅标题大小写不同的文档视为重复,要保留原标题格式的其中一份文档,同时移除其他重复项。之前的聚合方案因为把标题转小写后输出,导致丢失原格式,调整聚合逻辑就能解决这个问题。
正确的聚合去重查询
直接在分组时保留原文档的完整数据,而不是只输出小写标题:
db.article_titles.aggregate([ // 按小写标题、authorId、year分组,每组保留第一个原文档 { $group: { _id: { lowerTitle: { $toLower: "$title" }, authorId: "$authorId", year: "$year" }, originalDoc: { $first: "$$ROOT" } // 保留每组第一个完整原文档 } }, // 将原文档作为输出的根文档 { $replaceRoot: { newRoot: "$originalDoc" } }, // 输出到临时集合tmp(如果需要覆盖原集合,后续可替换) { $out: "tmp" } ])
步骤说明
$group阶段:用lowerTitle(小写标题)、authorId、year作为分组依据,确保大小写不同但内容一致的标题被归为同一组;$first: "$$ROOT"会保留每组中最先出现的完整原文档,这样原标题的格式(比如COVID-19的大写)就完全保留了。$replaceRoot阶段:把保留的原文档提升为输出的根文档,确保输出的结构和原集合一致。$out阶段:将去重后的结果写入临时集合tmp,方便后续验证或替换原集合。
替换原集合(可选)
如果确认临时集合tmp的数据符合要求,可以替换原集合:
// 先备份原集合(可选但建议) db.article_titles.renameCollection("article_titles_backup") // 将临时集合重命名为原集合名 db.tmp.renameCollection("article_titles")
直接删除原集合中的重复项(另一种方案)
如果不想用临时集合,也可以先查询出需要删除的重复项ID,再执行删除:
// 找出每组中需要删除的重复项ID(保留第一个,删除其他) const duplicates = db.article_titles.aggregate([ { $group: { _id: { lowerTitle: { $toLower: "$title" }, authorId: "$authorId", year: "$year" }, ids: { $push: "$_id" }, count: { $sum: 1 } }, $match: { count: { $gt: 1 } } }, { $project: { idsToDelete: { $slice: ["$ids", 1, { $size: "$ids" }] } // 排除第一个ID,剩下的是要删除的 } } ]).toArray() // 遍历结果执行删除 duplicates.forEach(item => { db.article_titles.deleteMany({ _id: { $in: item.idsToDelete } }) })
这个方案会直接在原集合中删除重复项,保留每组的第一个文档,同样不会破坏原标题格式。
内容的提问来源于stack exchange,提问作者user110920
相关产品推荐
相关产品推荐

