Mongodb - 数据模型更改,将数组转换为字符串的最佳方式
Mongodb - Data model change, optimal way of converting array to string
我们之前的数据模型假设某个字段,暂且暂且称它为field
,可以包含多个值,所以我们将其建模为一个数组。
初始模型:
{
field: ['val1]
}
然后我们意识到(1000 万个文档之后)情况并非如此,并更改为:
{
field: 'val1;
}
我认为迁移到新模型很简单,但显然并非如此。
我试过了:
db.collection.update({},{$rename: {"field.0": 'newField'}})
但它抱怨说数组元素不能用在 $rename
运算符的第一位。
据我了解,在更新操作中您不能将一个字段值分配给另一个字段值,我调查了聚合框架,但我想不出办法。
- 我可以使用聚合 fw 和
$out
运算符编辑文档来完成我想要的吗?
我也试过 foreach
,但是速度太慢了:
db.coll.find({"field":{$exists:true}}).snapshot().forEach(function(doc)
{
doc.newField = doc.field[0];
delete doc.field;
db.coll.save(doc);
});
我使用 bash 脚本将它并行化,我能够达到大约 200 updates/s,这意味着 10.000.000/(200*60*60)= 14h
,等待相当长的时间,而不考虑超时错误我处理 bash 脚本,但那会浪费更多时间。
所以现在我问,批量操作或聚合框架是否有可能加快这个过程?
会选择批量操作,因为它们允许执行批量更新操作,这些操作只是服务器顶部的抽象,可以轻松构建批量操作,从而简化您的更新。当 bulk API
批量发送写入操作时,您可以获得大型集合的性能提升,甚至更好的是,它会为您提供有关成功和失败的真实反馈。在批量更新中,您将以 1000 次为单位向服务器发送操作,这会给您带来更好的性能,因为您不会向服务器发送每个请求,每 1000 个请求只发送一次:
var bulk = db.collection.initializeOrderedBulkOp(),
counter = 0;
db.collection.find({"field": { "$exists": true, "$type": 4 }}).forEach(function(doc) {
var updatedVal = doc.field[0];
bulk.find({ "_id": doc._id }).updateOne({
"$set": { "field": updatedVal }
});
counter++;
if (counter % 1000 == 0) {
bulk.execute(); // Execute per 1000 operations and re-initialize every 1000 update statements
bulk = db.collection.initializeUnorderedBulkOp();
}
});
// Clean up queues
if (counter % 1000 != 0) { bulk.execute(); }
我们之前的数据模型假设某个字段,暂且暂且称它为field
,可以包含多个值,所以我们将其建模为一个数组。
初始模型:
{
field: ['val1]
}
然后我们意识到(1000 万个文档之后)情况并非如此,并更改为:
{
field: 'val1;
}
我认为迁移到新模型很简单,但显然并非如此。
我试过了:
db.collection.update({},{$rename: {"field.0": 'newField'}})
但它抱怨说数组元素不能用在 $rename
运算符的第一位。
据我了解,在更新操作中您不能将一个字段值分配给另一个字段值,我调查了聚合框架,但我想不出办法。
- 我可以使用聚合 fw 和
$out
运算符编辑文档来完成我想要的吗?
我也试过 foreach
,但是速度太慢了:
db.coll.find({"field":{$exists:true}}).snapshot().forEach(function(doc)
{
doc.newField = doc.field[0];
delete doc.field;
db.coll.save(doc);
});
我使用 bash 脚本将它并行化,我能够达到大约 200 updates/s,这意味着 10.000.000/(200*60*60)= 14h
,等待相当长的时间,而不考虑超时错误我处理 bash 脚本,但那会浪费更多时间。
所以现在我问,批量操作或聚合框架是否有可能加快这个过程?
会选择批量操作,因为它们允许执行批量更新操作,这些操作只是服务器顶部的抽象,可以轻松构建批量操作,从而简化您的更新。当 bulk API
批量发送写入操作时,您可以获得大型集合的性能提升,甚至更好的是,它会为您提供有关成功和失败的真实反馈。在批量更新中,您将以 1000 次为单位向服务器发送操作,这会给您带来更好的性能,因为您不会向服务器发送每个请求,每 1000 个请求只发送一次:
var bulk = db.collection.initializeOrderedBulkOp(),
counter = 0;
db.collection.find({"field": { "$exists": true, "$type": 4 }}).forEach(function(doc) {
var updatedVal = doc.field[0];
bulk.find({ "_id": doc._id }).updateOne({
"$set": { "field": updatedVal }
});
counter++;
if (counter % 1000 == 0) {
bulk.execute(); // Execute per 1000 operations and re-initialize every 1000 update statements
bulk = db.collection.initializeUnorderedBulkOp();
}
});
// Clean up queues
if (counter % 1000 != 0) { bulk.execute(); }