我正在使用express.js服务器。我正在尝试更新mongodb集合中的现有文档使用mongoose 与对象数组(每个对象具有_id
属性,其值对应于每个文档_id
。)
一种方法是循环数组并执行findByIdAndUpdate()
for(var i=0; i < expenseListToEdit.length; i++) {
var expense = expenseListToEdit[i];
Expense.findByIdAndUpdate(expense._id, expense, function(err, model) {
if (err) {
console.log('Error occurred while editing expense');
}
console.log('model: ' + util.inspect(model));
});
}
但是这样我将不得不处理异步场景,并且必须检查所有迭代的db查询何时完成,然后才将响应从服务器发送回客户端。
mongoose中是否有任何替代方法可以一次编辑/修改对象数组然后调用回调?
注意* - 每个数组对象都有_id
,它与文档_id
值匹配。
答案 0 :(得分:0)
是的,这很有可能。您可以利用批量写入API来处理异步操作,从而提高性能,尤其是处理大型数据集。对于支持>=4.3.0
的Mongoose版本MongoDB Server 3.2.x
,
您可以使用 bulkWrite()
进行更新。以下示例说明了如何解决此问题:
var bulkUpdateCallback = function(err, r){
console.log(r.matchedCount);
console.log(r.modifiedCount);
}
// Initialise the bulk operations array
var bulkOps = expenseListToEdit.map(function (expense) {
return {
"updateOne": {
"filter": { "_id": expense._id } ,
"update": { "$set": expense }
}
}
});
// Get the underlying collection via the native node.js driver collection object
Expense.collection.bulkWrite(bulkOps, { "ordered": true, w: 1 }, bulkUpdateCallback);
对于支持MongoDB服务器~3.8.8, ~3.8.22, 4.x
的Mongoose版本>=2.6.x
,您可以使用 Bulk API
,如下所示
var bulk = Expense.collection.initializeOrderedBulkOp(),
counter = 0;
expenseListToEdit.forEach(function(expense) {
bulk.find({ "_id": expense._id })
.updateOne({ "$set": expense });
counter++;
if (counter % 500 == 0) {
bulk.execute(function(err, r) {
// do something with the result
bulk = Expense.collection.initializeOrderedBulkOp();
counter = 0;
});
}
});
// Catch any docs in the queue under or over the 500's
if (counter > 0) {
bulk.execute(function(err, result) {
// do something with the result here
});
}
答案 1 :(得分:0)
解决方案是按for
http://caolan.github.io/async/docs.html#each更改async.each
语句:
警告:每个元素并行启动所有元素。
async.each(expenseListToEdit, function (expense, done) {
Expense.findByIdAndUpdate(expense._id, expense, function(err, model) {
if (err) {
console.log('Error occurred while editing expense');
done(err); // if an error occured, all each is stoped
return;
}
console.log('model: ' + util.inspect(model));
done();
});
}, function (err) {
// final callback launched after all findByIdAndUpdate calls.
});
答案 2 :(得分:0)
for (let i of expenseListToEdit) {
Expense.findByIdAndUpdate(i._id, {})
.exec()
.then(function updated(expense) {
if (expense) {
//DO SMTH
}
}).then(null, function(err) {
console.error(err)
throw err;
})
}