MongoDB如何编写查询删除同一empId和enrollDate下的重复记录
前置注意事项
操作前务必先对目标集合做全量备份,先执行查询语句确认要删除的文档内容、数量符合预期后,再执行删除操作,避免误删数据。
实现方案(MongoDB 4.2+ 推荐)
第一步:先查询待删除的文档做校验
执行以下聚合语句,确认返回的文档全部是需要删除的5/21/2021重复记录,注意把代码中你的集合名.replaceThisWithYourCollectionName替换为实际的集合名:
db.你的集合名.replaceThisWithYourCollectionName.aggregate([ { $match: { empId: {$in: ["101962700", "101962701"]}, enrollDate: "5/21/2021" } }, { $group: { _id: "$empId", allDocIds: {$push: "$_id"} } }, { $project: { // 跳过每个分组下的第一个_id,剩下的都是要删除的id deleteIds: {$slice: ["$allDocIds", 1, {$size: "$allDocIds"}]} } }, {$unwind: "$deleteIds"}, {$replaceRoot: {newRoot: {_id: "$deleteIds"}}} ])
第二步:执行删除操作
校验无误后执行以下deleteMany语句完成删除:
db.你的集合名.replaceThisWithYourCollectionName.deleteMany({ _id: { $in: db.你的集合名.replaceThisWithYourCollectionName.aggregate([ { $match: { empId: {$in: ["101962700", "101962701"]}, enrollDate: "5/21/2021" } }, { $group: { _id: "$empId", allDocIds: {$push: "$_id"} } }, { $project: { deleteIds: {$slice: ["$allDocIds", 1, {$size: "$allDocIds"}]} } }, {$unwind: "$deleteIds"} ]).map(item => item.deleteIds) } })
低版本MongoDB兼容方案
如果使用的是4.2以下版本的MongoDB,可以用游标遍历的方式实现:
// 遍历两个目标empId ["101962700", "101962701"].forEach(targetEmpId => { // 查找当前empId下5/21/2021的所有记录,跳过第一条保留,剩余全部删除 const toDeleteDocs = db.你的集合名.replaceThisWithYourCollectionName.find({ empId: targetEmpId, enrollDate: "5/21/2021" }).skip(1).toArray(); toDeleteDocs.forEach(doc => { db.你的集合名.replaceThisWithYourCollectionName.remove({_id: doc._id}); }) })
可选配置
如果需要指定保留最新/最旧的一条记录,可以在find或者聚合的$group前添加$sort规则:
- 保留最新创建的记录:添加
{$sort: {createdDateTime: -1}} - 保留最早创建的记录:添加
{$sort: {createdDateTime: 1}}
内容的提问来源于stack exchange,提问作者Sandeep Deshpande
相关产品推荐
相关产品推荐

