如何查找并移除数据库集合文档中的重复键 优先删除值为null的项
数据库集合重复键排查与清理方案
排查存在重复键的文档
由于常规JSON解析会默认覆盖重复键,需要遍历原始BSON记录检测重复,以MongoDB为例,执行以下脚本即可输出所有含重复键的文档ID和对应重复键:
// 替换为实际集合名称 const targetColl = db.getCollection("your_collection_name"); const duplicateKeyRecords = []; targetColl.find().forEach(doc => { const keyStat = {}; const currentDupKeys = []; Object.keys(doc).forEach(key => { keyStat[key] = (keyStat[key] || 0) + 1; if (keyStat[key] === 2) currentDupKeys.push(key); }) if (currentDupKeys.length) { duplicateKeyRecords.push({ _id: doc._id, duplicateKeys: currentDupKeys }) } }) printjson(duplicateKeyRecords);
清理重复键
方案1:删除值为null的重复键
duplicateKeyRecords.forEach(record => { const doc = targetColl.findOne({_id: record._id}); const unsetOps = {}; record.duplicateKeys.forEach(key => { if (doc[key] === null) unsetOps[key] = ""; }) if (Object.keys(unsetOps).length) { targetColl.updateOne( {_id: record._id}, {$unset: unsetOps} ); } })
方案2:删除先出现的重复键,保留后出现的
数据库驱动读取文档时默认会用后出现的键值覆盖先出现的,直接重写文档即可自动去重:
duplicateKeyRecords.forEach(record => { const doc = targetColl.findOne({_id: record._id}); targetColl.replaceOne({_id: record._id}, doc); })
注意事项
- 操作前必须备份全量集合数据,避免误操作导致数据丢失
- 数据量较大的集合建议分批处理,避免占用过多数据库资源
- 清理完成后可重新执行排查脚本,确认重复键已全部清理
内容的提问来源于stack exchange,提问作者Dao Kieu Vi
相关产品推荐
相关产品推荐

