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

MongoDB 3.6文档结构迁移:合并新旧格式数据方案咨询

解决MongoDB混合格式文档的结构迁移问题

问题背景

需要将MongoDB集合productDetails中的数据从旧结构迁移至新结构:

  • 旧结构:_id为字符串类型
  • 新结构:_id是包含productId(原_id值)和countryCode(固定值DE)的复合对象
  • 集合当前包含约4000万旧格式文档,以及70万已完成转换的新格式文档
  • 使用MongoDB 3.6,计划通过聚合函数创建新集合后替换旧集合,但现有聚合语句会错误覆盖已有的新格式文档,需修正。

旧结构示例

{
  "_id": "some-id",
  "_class": "org.some.class",
  "number": 1015,
  "timestamp": {"$date": "2020-09-05T12:08:02.809Z"},
  "cost": 0.9200000166893005
}

新结构示例

{
  "_id": {
    "productId": "some-id",
    "countryCode": "DE"
  },
  "_class": "org.some.class",
  "number": 1015,
  "timestamp": {"$date": "2020-09-05T12:08:02.809Z"},
  "cost": 0.9200000166893005
}

现有语句问题

原聚合语句会对所有文档强制重新构造_id,包括已转换的新格式文档,导致这部分数据被错误修改,无法保留:

db.productDetails.aggregate(
  {$match: {_id: {$exists: true}}},
  {$addFields: {"_id": {"productId": "$_id", "country": "DE"}}},
  {$project: {_id: 1, _class: 1, number: 1, timestamp: 1, cost: 1}},
  {$out: "productDetailsV2"}
)

正确聚合方案

通过$cond判断_id的类型,仅对字符串类型的旧格式文档进行转换,保留已有的新格式文档,同时修正字段名(原语句中country应为countryCode):

db.productDetails.aggregate([
  {
    $addFields: {
      "_id": {
        $cond: {
          if: {$eq: [{$type: "$_id"}, "string"]},
          then: {productId: "$_id", countryCode: "DE"},
          else: "$_id"
        }
      }
    }
  },
  {
    $project: {
      _id: 1,
      _class: 1,
      number: 1,
      timestamp: 1,
      cost: 1
    }
  },
  {
    $out: "productDetailsV2"
  }
])

关键逻辑说明

  1. 类型判断:使用$type检查_id的类型,字符串类型为旧格式文档,对象类型为已转换的新格式文档
  2. 条件转换:仅对旧格式文档生成复合_id,新格式文档直接保留原_id
  3. 字段修正:将原语句中的country改为countryCode,与目标结构一致
  4. 输出集合:将结果写入新集合productDetailsV2,避免直接修改原集合

注意事项

  • 执行前务必备份原集合,防止数据丢失
  • 数据量较大(约4700万条),建议在业务低峰期执行,避免影响正常业务
  • MongoDB 3.6支持$type操作符判断字段类型,字符串类型对应值为"string",对象类型对应值为"object"

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 15:25:20