【问题标题】:MongoDB: Update a string field in all documentsMongoDB:更新所有文档中的字符串字段
【发布时间】:2016-09-26 01:36:32
【问题描述】:
我有一个 MongoDB 数据库,其中包含许多文档。每篇文章都有一个名为myField 的字段,其中包含一个字符串。
我是否可以对集合中的所有个文档运行批量更新,为每个文档修改myField 的值?
在我的例子中,我只想从每个字段中去掉一个尾随的“.html”。我在我的应用程序中使用 node.js 与 Mongo 进行交互,但如果可能的话,我希望能够在 mongo 命令提示符上运行单个命令来执行此更新。
【问题讨论】:
标签:
javascript
node.js
mongodb
database
【解决方案1】:
是的,可以使用 mongo 从命令提示符更新 mongoDB 文档信息。
说出脚本文件名migration.js 并转到此文件目录并打开命令提示符并运行此命令。
mongo localhost/dbName migration.js
和migration.js 类似代码:
print('Please wait it may will take some time to complete migration');
print('....');
db.collectionName.find().forEach( function(doc) {
if(!doc._id) {
print('No doc found');
return;
}
// if need can apply logic to update myField
db.collectionName.update({_id: doc._id}, {$set: {myField: "newVale"}});
});
print('Migration has been completed :)');
【解决方案2】:
考虑使用 bulkWrite API 来利用更新,因为它比在循环中进行更新更好、更有效地处理这一点,即每次迭代发送每个更新请求可能会很慢数据集。
bulkWrite API 以 500 次为单位将写入发送到服务器,这可以为您提供更好的性能,因为您不会将每个请求都发送到服务器,而是每 500 个请求发送一次。
对于批量操作,MongoDB 对每个批次强制执行 default internal limit of 1000 操作,因此从某种意义上说,选择 500 个文档会很好,因为您可以对批次大小进行一些控制,而不是让 MongoDB 强制执行默认值,即对于较大的操作> 1000 个文档的大小。
举个例子:
var bulkUpdateOps = [], // create an array to hold the update operations
counter = 0, // counter to control the batch sizes
rgx = /\.(html)$/i, // regex for querying and updating the field
cursor = db.collection.find({ "myField": rgx }); // cursor for iterating
cursor.snapshot().forEach(function(doc) {
var updatedField = doc.myField.replace(rgx, ''); // update field
bulkUpdateOps.push({ // queue the update operations to an array
"updateOne": {
"filter": {
"_id": doc._id,
"myField": { "$ne": updatedField }
},
"update": { "$set": { "myField": updatedField } }
}
});
counter++;
if (counter % 500 == 0) { // send the update ops in bulk
db.collection.bulkWrite(bulkUpdateOps);
bulkUpdateOps = []; // reset the array
}
})
if (counter % 500 != 0) { // clean up remaining operations in the queue
db.collection.bulkWrite(bulkUpdateOps)
}