我想要使用不同的值更新多个文档。
我的数据库看起来像这样。
[
{
"_id": 1,
"value": 50
},
{
"_id": 2,
"value": 100
}
]
此查询返回错误,因为我在$ set中传递数组而不是对象。
Model.update({_id: {$in: ids}}, {$set: ids.value}, {multi: true};
我希望我的数据库看起来像这样
[
{
"_id": 1,
"value": 4
},
{
"_id": 2,
"value": 27
}
]
答案 0 :(得分:6)
假设您有一组对象要在集合中更新匹配的ID,如
var soldItems = [
{
"_id": 1,
"value": 4
},
{
"_id": 2,
"value": 27
}
];
然后你可以使用数组上的 forEach()
方法来迭代它并更新你的集合:
soldItems.forEach(function(item)){
Model.update({"_id": item._id}, {"$set": {"value": item.value }}, callback);
});
或使用承诺
var updates = [];
soldItems.forEach(function(item)){
var updatePromise = Model.update({"_id": item._id}, {"$set": {"value": item.value }});
updates.push(updatePromise);
});
Promise.all(updates).then(function(results){
console.log(results);
});
或使用 map()
var updates = soldItems.map(function(item)){
return Model.update({"_id": item._id}, {"$set": {"value": item.value }});
});
Promise.all(updates).then(function(results){
console.log(results);
});
对于较大的阵列,您可以利用批量写入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 = soldItems.map(function (item) {
return {
"updateOne": {
"filter": { "_id": item._id } ,
"update": { "$set": { "value": item.value } }
}
}
});
// Get the underlying collection via the native node.js driver collection object
Model.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 = Model.collection.initializeOrderedBulkOp(),
counter = 0;
soldItems.forEach(function(item) {
bulk.find({ "_id": item._id }).updateOne({
"$set": { "value": item.value }
});
counter++;
if (counter % 500 == 0) {
bulk.execute(function(err, r) {
// do something with the result
bulk = Model.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 :(得分:3)
首先,您的update()
查询不正确..
请参阅此here
的文档
Model.update(conditions, update, options, callback);
假设您当前的数据库模型包含这样的文档(正如您所描述的那样):
[
{
"_id": 1,
"value": 50
},
{
"_id": 2,
"value": 100
}
];
并且您在下面的数组中包含要使用当前db的文档修改的对象(即文档),如下所示:
idsArray: [
{
"_id": 1,
"value": 4
},
{
"_id": 2,
"value": 27
}
];
根据我对mongodb& amp ;;的经验mongoose,我不认为你可以使用单行查询更新所有文档(这是你想要做的)..(P.S。我不知道这个,所以我不确定这个..)
但为了使你的代码有效,你将会做这样的事情:
想法:遍历文档中的每个文档,即idsArray
并在其上调用update()..
所以,这是代码:
idsArray.forEach(function(obj) {
Model.update({_id: obj._id}, {$set: {value: obj.value}});
});
在上面的代码中,我假设你在db docs中有_id
个值,因为它们在上面写了(即"_id": 1
)..但是如果它们是这样的{{1} }
"_id": ObjectId('1')
然后您需要在update()查询中将[
{
"_id": ObjectId('1'),
"value": 50
},
.....
.....
]
转换为_id
。
所以你会这样做。
ObjectId(obj._id)
P.S。在前进之前确认一下(即var ObjectId = require('mongodb').ObjectID;
idsArray.forEach(function(obj) {
Model.update({_id: ObjectId(obj._id)}, {$set: {value: obj.value}});
});
)..
希望这有帮助。
干杯,
答案 2 :(得分:1)
多次更新只能用于将多个文档更新为相同的值,或者使用相同的update operation更新所有文档。
如果要更新为不同的值,则必须使用多个更新语句。