You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用mongorestore合并MongoDB数据库未恢复全部文档的问题

解决MongoDB合并时mongorestore重复键导致部分文档未导入的问题

问题根源

虽然文档_id无冲突,但目标集合存在非_id的唯一索引,导致导入时触发重复键错误(E1000),mongorestore会跳过冲突文档,最终部分数据未成功导入。

解决步骤

1. 定位冲突的唯一索引

在目标数据库中查询集合的所有索引,找到标记为unique: true的非_id索引:

db.PoiAnalysis2.getIndexes()

输出结果中会包含类似如下的唯一索引项:

{
  "v" : 2,
  "key" : { "some_business_field" : 1 },
  "name" : "some_business_field_1",
  "unique" : true
}

这里的some_business_field就是导致重复键冲突的字段。

2. 临时移除唯一约束(或跳过索引恢复)

有两种方式处理:

  • 方式一:删除目标集合的冲突唯一索引
    直接删除该唯一索引,避免导入时触发冲突:
    db.PoiAnalysis2.dropIndex("some_business_field_1")
    
  • 方式二:mongorestore时跳过索引恢复
    如果不想提前修改目标集合,可在导入命令中添加--noIndexRestore参数,暂时不恢复索引:
    mongorestore --uri="mongodb://admin:password@localhost:27017/my_db?authSource=admin" --dir=my_db --authenticationDatabase=admin --numInsertionWorkersPerCollection=4 --gzip --noIndexRestore
    

3. 重新执行mongorestore导入

用修改后的命令重新导入,此时所有文档都会被写入目标集合(不会因唯一键冲突被跳过)。

4. 处理重复数据并重建索引(可选)

如果业务上需要保留该字段的唯一约束,导入完成后需先清理重复数据,再重建唯一索引:

  • 清理重复数据(保留最新文档)
    假设冲突字段为some_business_field,按_date_created保留最新的文档:
    db.PoiAnalysis2.aggregate([
      { $group: { 
          _id: "$some_business_field", 
          docs: { $push: "$$ROOT" }, 
          count: { $sum: 1 } 
        }
      },
      { $match: { count: { $gt: 1 } } }
    ]).forEach(function(group) {
      // 按创建时间倒序排序,保留第一个(最新),删除其余
      group.docs.sort((a, b) => b._date_created - a._date_created);
      for (let i = 1; i < group.docs.length; i++) {
        db.PoiAnalysis2.deleteOne({ _id: group.docs[i]._id });
      }
    });
    
  • 重建唯一索引
    清理完成后,重新创建唯一索引:
    db.PoiAnalysis2.createIndex({ some_business_field: 1 }, { unique: true })
    

5. 验证导入结果

执行原查询确认最新文档已导入:

db.getCollection("PoiAnalysis2").find({}).sort({_date_created: -1}).limit(1)

内容的提问来源于stack exchange,提问作者Tom McLean

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 05:04:54