MongoDB,将元素数据类型从数字字符串转换为大型集合的数字 (3kk)

MongoDB, convert element data type from numeric string to number for a large collection (3kk)

我有一个很大的 3kk mongodb 集合,我需要将其中的一个元素从数字字符串转换为数字。

我正在使用 mongo-shell 脚本,该脚本适用于 10 万个元素的小型集合,请参阅以下脚本:

db.SurName.find().forEach(function(tmp){
    tmp.NUMBER = parseInt(tmp.NUMBER);
    db.SurName.save(tmp);
})

但是在工作了十几分钟后我得到了一个错误(即使集合更小如 1kk 也会出现错误):

MongoDB Enterprise Test-shard-0:PRIMARY> db.SurName.find().forEach(function(tmp){
...         tmp.NUMBER = parseInt(tmp.NUMBER);
... db.SurName.save(tmp);
...     })
2020-01-18T16:59:21.173+0100 E  QUERY    [js] Error: command failed: {
        "operationTime" : Timestamp(1579363161, 14),
        "ok" : 0,
        "errmsg" : "cursor id 4811116025485863761 not found",
        "code" : 43,
        "codeName" : "CursorNotFound",
        "$clusterTime" : {
                "clusterTime" : Timestamp(1579363161, 14),
                "signature" : {
                        "hash" : BinData(0,"EemWWenbArSdh4dTFa0aNcfAPms="),
                        "keyId" : NumberLong("6748451824648323073")
                }
        }
} : getMore command failed: {
        "operationTime" : Timestamp(1579363161, 14),
        "ok" : 0,
        "errmsg" : "cursor id 4811116025485863761 not found",
        "code" : 43,
        "codeName" : "CursorNotFound",
        "$clusterTime" : {
                "clusterTime" : Timestamp(1579363161, 14),
                "signature" : {
                        "hash" : BinData(0,"EemWWenbArSdh4dTFa0aNcfAPms="),
                        "keyId" : NumberLong("6748451824648323073")
                }
        }
} :
_getErrorWithCode@src/mongo/shell/utils.js:25:13
doassert@src/mongo/shell/assert.js:18:14
_assertCommandWorked@src/mongo/shell/assert.js:583:17
assert.commandWorked@src/mongo/shell/assert.js:673:16
DBCommandCursor.prototype._runGetMoreCommand@src/mongo/shell/query.js:802:5
DBCommandCursor.prototype._hasNextUsingCommands@src/mongo/shell/query.js:832:9
DBCommandCursor.prototype.hasNext@src/mongo/shell/query.js:840:16
DBQuery.prototype.hasNext@src/mongo/shell/query.js:288:13
DBQuery.prototype.forEach@src/mongo/shell/query.js:493:12
@(shell):1:1

有没有办法做到这一点better/right?

编辑: 对象模式:

{"_id":{"$oid":"5e241b98c7cab1382c7c9d95"},
"SURNAME":"KOWALSKA",
"SEX":"KOBIETA",
"TERYT":"0201011",
"NUMBER":"51",
"COMMUNES":"BOLESŁAWIEC",
"COUNTIES":"BOLESŁAWIECKI",
"PROVINCES":"DOLNOŚLĄSKIE"
}

** 编辑 - 开始 **

谷歌搜索 "cursor id not found code 43",得到了这个答案:

** 编辑 - 结束 **

我没有你的数据集,所以我不能很好地测试我的答案。也就是说,您可以尝试 Update 特定字段(请参阅文档中的更新:db.collection.update

因此您的脚本将如下所示:

db.SurName.find({}, {NUMBER: 1}).forEach(function(tmp){
    db.SurName.update({_id: tmp._id}, {$set: {NUMBER: parseInt(tmp.NUMBER)}});
})

让我知道是否有帮助或是否需要编辑

最佳且快速的解决方案是将 mongodb aggregation$out 运算符一起使用。

相当于:

insert into new_table
select * from old_table

我们使用$toInt(MongoDB版本>=4.0)运算符转换NUMBER字段,并将文档存储在SurName2集合中。完成后,我们只需删除旧集合并将 SurName2 集合重命名为 SurName.

db.SurName.aggregate([
  {$addFields:{
    NUMBER : {$toInt:"$NUMBER"}
  }},
  {$out: "SurName2"}
])

检查一切正常后,执行以下语句:

db.SurName.drop()
db.SurName2.renameCollection("SurName")