MongoDB shell 中的无序批量更新记录
Unordered bulk update records in MongoDB shell
我有一个包含数百万个文档的集合,类似于以下内容:
{
_id: ObjectId('...'),
value: "0.53"
combo: [
{
h: 0,
v: "0.42"
},
{
h: 1,
v: "1.32"
}
]
}
问题是值存储为字符串,我需要将它们转换为 float/double。
我正在尝试这个并且它正在工作但是这需要几天才能完成,考虑到数据量:
db.collection.find({}).forEach(function(obj) {
if (typeof(obj.value) === "string") {
obj.value = parseFloat(obj.value);
db.collection.save(obj);
}
obj.combo.forEach(function(hv){
if (typeof(hv.value) === "string") {
hv.value = parseFloat(hv.value);
db.collection.save(obj);
}
});
});
我在阅读 Mongo 文档时遇到了批量更新,我正在尝试这样做:
var bulk = db.collection.initializeUnorderedBulkOp();
bulk.find({}).update(
{
$set: {
"value": parseFloat("value"),
}
});
bulk.execute();
这会运行...但是我得到一个 NAN 作为值,这是因为它认为我正在尝试将 "value" 转换为浮点数。我尝试了不同的变体,例如 this.value
和 "$value"
但无济于事。此外,此方法仅尝试更正另一个对象中的值,而不是数组中的值。
如果有任何帮助,我将不胜感激。提前致谢!
通过以下方式计算出来:
1) 为了在文档级别进行转换,我遇到了 并且 Markus 的回复为我的解决方案铺平了道路:
var bulk = db.collection.initializeUnorderedBulkOp()
var myDocs = db.collection.find()
var ops = 0
myDocs.forEach(
function(myDoc) {
bulk.find({ _id: myDoc._id }).updateOne(
{
$set : {
"value": parseFloat(myDoc.value),
}
}
);
if ((++ops % 1000) === 0){
bulk.execute();
bulk = db.collection.initializeUnorderedBulkOp();
}
}
)
bulk.execute();
2) 第二部分涉及更新数组对象值,我在 this post 上接受的答案中发现了这样做的语法。就我而言,我知道 I 运行 中有 24 个值与第一个查询分开,结果如下所示:
var bulk = db.collection.initializeUnorderedBulkOp()
var myDocs = db.collection.find()
var ops = 0
myDocs.forEach(
function(myDoc) {
bulk.find({ _id: myDoc._id }).update(
{
$set : {
"combo.0.v": parseFloat(myDoc.combo[0].v),
"combo.1.v": parseFloat(myDoc.combo[1].v),
"combo.2.v": parseFloat(myDoc.combo[2].v),
"combo.3.v": parseFloat(myDoc.combo[3].v),
"combo.4.v": parseFloat(myDoc.combo[4].v),
"combo.5.v": parseFloat(myDoc.combo[5].v),
"combo.6.v": parseFloat(myDoc.combo[6].v),
"combo.7.v": parseFloat(myDoc.combo[7].v),
"combo.8.v": parseFloat(myDoc.combo[8].v),
"combo.9.v": parseFloat(myDoc.combo[9].v),
"combo.10.v": parseFloat(myDoc.combo[10].v),
"combo.11.v": parseFloat(myDoc.combo[11].v),
"combo.12.v": parseFloat(myDoc.combo[12].v),
"combo.13.v": parseFloat(myDoc.combo[13].v),
"combo.14.v": parseFloat(myDoc.combo[14].v),
"combo.15.v": parseFloat(myDoc.combo[15].v),
"combo.16.v": parseFloat(myDoc.combo[16].v),
"combo.17.v": parseFloat(myDoc.combo[17].v),
"combo.18.v": parseFloat(myDoc.combo[18].v),
"combo.19.v": parseFloat(myDoc.combo[19].v),
"combo.20.v": parseFloat(myDoc.combo[20].v),
"combo.21.v": parseFloat(myDoc.combo[21].v),
"combo.22.v": parseFloat(myDoc.combo[22].v),
"combo.23.v": parseFloat(myDoc.combo[23].v)
}
}
);
if ((++ops % 1000) === 0){
bulk.execute();
bulk = db.collection.initializeUnorderedBulkOp();
}
}
)
bulk.execute();
只是给出一个关于性能的想法,forEach
每分钟处理大约 900 个文档,如果是 1500 万条记录,这实际上需要几天时间!不仅如此,这只是在文档级别转换类型,而不是数组级别。为此,我将不得不循环遍历每个文档并循环遍历每个数组(1500 万 x 24 次迭代)!使用这种方法(运行 两个查询并排),它在 6 小时内完成。
我希望这对其他人有帮助。
我有一个包含数百万个文档的集合,类似于以下内容:
{
_id: ObjectId('...'),
value: "0.53"
combo: [
{
h: 0,
v: "0.42"
},
{
h: 1,
v: "1.32"
}
]
}
问题是值存储为字符串,我需要将它们转换为 float/double。
我正在尝试这个并且它正在工作但是这需要几天才能完成,考虑到数据量:
db.collection.find({}).forEach(function(obj) {
if (typeof(obj.value) === "string") {
obj.value = parseFloat(obj.value);
db.collection.save(obj);
}
obj.combo.forEach(function(hv){
if (typeof(hv.value) === "string") {
hv.value = parseFloat(hv.value);
db.collection.save(obj);
}
});
});
我在阅读 Mongo 文档时遇到了批量更新,我正在尝试这样做:
var bulk = db.collection.initializeUnorderedBulkOp();
bulk.find({}).update(
{
$set: {
"value": parseFloat("value"),
}
});
bulk.execute();
这会运行...但是我得到一个 NAN 作为值,这是因为它认为我正在尝试将 "value" 转换为浮点数。我尝试了不同的变体,例如 this.value
和 "$value"
但无济于事。此外,此方法仅尝试更正另一个对象中的值,而不是数组中的值。
如果有任何帮助,我将不胜感激。提前致谢!
通过以下方式计算出来:
1) 为了在文档级别进行转换,我遇到了
var bulk = db.collection.initializeUnorderedBulkOp()
var myDocs = db.collection.find()
var ops = 0
myDocs.forEach(
function(myDoc) {
bulk.find({ _id: myDoc._id }).updateOne(
{
$set : {
"value": parseFloat(myDoc.value),
}
}
);
if ((++ops % 1000) === 0){
bulk.execute();
bulk = db.collection.initializeUnorderedBulkOp();
}
}
)
bulk.execute();
2) 第二部分涉及更新数组对象值,我在 this post 上接受的答案中发现了这样做的语法。就我而言,我知道 I 运行 中有 24 个值与第一个查询分开,结果如下所示:
var bulk = db.collection.initializeUnorderedBulkOp()
var myDocs = db.collection.find()
var ops = 0
myDocs.forEach(
function(myDoc) {
bulk.find({ _id: myDoc._id }).update(
{
$set : {
"combo.0.v": parseFloat(myDoc.combo[0].v),
"combo.1.v": parseFloat(myDoc.combo[1].v),
"combo.2.v": parseFloat(myDoc.combo[2].v),
"combo.3.v": parseFloat(myDoc.combo[3].v),
"combo.4.v": parseFloat(myDoc.combo[4].v),
"combo.5.v": parseFloat(myDoc.combo[5].v),
"combo.6.v": parseFloat(myDoc.combo[6].v),
"combo.7.v": parseFloat(myDoc.combo[7].v),
"combo.8.v": parseFloat(myDoc.combo[8].v),
"combo.9.v": parseFloat(myDoc.combo[9].v),
"combo.10.v": parseFloat(myDoc.combo[10].v),
"combo.11.v": parseFloat(myDoc.combo[11].v),
"combo.12.v": parseFloat(myDoc.combo[12].v),
"combo.13.v": parseFloat(myDoc.combo[13].v),
"combo.14.v": parseFloat(myDoc.combo[14].v),
"combo.15.v": parseFloat(myDoc.combo[15].v),
"combo.16.v": parseFloat(myDoc.combo[16].v),
"combo.17.v": parseFloat(myDoc.combo[17].v),
"combo.18.v": parseFloat(myDoc.combo[18].v),
"combo.19.v": parseFloat(myDoc.combo[19].v),
"combo.20.v": parseFloat(myDoc.combo[20].v),
"combo.21.v": parseFloat(myDoc.combo[21].v),
"combo.22.v": parseFloat(myDoc.combo[22].v),
"combo.23.v": parseFloat(myDoc.combo[23].v)
}
}
);
if ((++ops % 1000) === 0){
bulk.execute();
bulk = db.collection.initializeUnorderedBulkOp();
}
}
)
bulk.execute();
只是给出一个关于性能的想法,forEach
每分钟处理大约 900 个文档,如果是 1500 万条记录,这实际上需要几天时间!不仅如此,这只是在文档级别转换类型,而不是数组级别。为此,我将不得不循环遍历每个文档并循环遍历每个数组(1500 万 x 24 次迭代)!使用这种方法(运行 两个查询并排),它在 6 小时内完成。
我希望这对其他人有帮助。