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")
我有一个很大的 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")