猫鼬多重更新

use*_*830 4 mongoose mongodb node.js express

我想更新具有不同值的多个文档.

我的数据库看起来像这样.

[
    {
        "_id": 1,
        "value": 50
    },
    {
        "_id": 2,
        "value": 100
    }
]
Run Code Online (Sandbox Code Playgroud)

此查询返回错误,因为我传递的是数组而不是$ set中的对象.

    Model.update({_id: {$in: ids}}, {$set: ids.value}, {multi: true};
Run Code Online (Sandbox Code Playgroud)

我希望我的数据库看起来像这样

[
        {
            "_id": 1,
            "value": 4
        },
        {
            "_id": 2,
            "value": 27
        }
    ]
Run Code Online (Sandbox Code Playgroud)

chr*_*dam 8

假设您有一组对象要在集合中更新匹配的ID,例如

var soldItems = [
        {
            "_id": 1,
            "value": 4
        },
        {
            "_id": 2,
            "value": 27
        }
    ];
Run Code Online (Sandbox Code Playgroud)

然后你可以使用forEach()数组上的方法来迭代它并更新你的集合:

soldItems.forEach(function(item)){
    Model.update({"_id": item._id}, {"$set": {"value": item.value }}, callback);
});
Run Code Online (Sandbox Code Playgroud)

或使用承诺作为

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);
});
Run Code Online (Sandbox Code Playgroud)

或使用 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);
}); 
Run Code Online (Sandbox Code Playgroud)

对于较大的阵列,您可以利用批量写入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);
Run Code Online (Sandbox Code Playgroud)

对于~3.8.8, ~3.8.22, 4.x支持MongoDB Server的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
    });
}
Run Code Online (Sandbox Code Playgroud)


nar*_*gar 5

首先,您的update()查询不正确..

请参阅此处的文档

Model.update(conditions, update, options, callback);

假设您当前的 db 模型包含这样的文档(正如您所描述的那样):

[
    {
        "_id": 1,
        "value": 50
    },
    {
        "_id": 2,
        "value": 100
   }
];
Run Code Online (Sandbox Code Playgroud)

并且您在包含要使用当前数据库的文档进行修改的对象(即文档)的数组下方是这样的:

idsArray: [
    {
        "_id": 1,
        "value": 4
    },
    {
        "_id": 2,
        "value": 27
    }
];
Run Code Online (Sandbox Code Playgroud)

根据我对 mongodb 和 mongoose 的经验,我认为您无法使用单行查询更新所有文档(这是您正在尝试执行的操作)..(PS 我不知道这一点,所以我不确定。 .)

但是为了使您的代码工作,您将执行以下操作:

想法:循环遍历 docs 中的每个文档,idsArray然后调用 update() 。

所以,这是代码:

idsArray.forEach(function(obj) {
    Model.update({_id: obj._id}, {$set: {value: obj.value}});
});
Run Code Online (Sandbox Code Playgroud)

在上面的代码中,我假设你_id在 db docs 中有值,因为它们是在上面写的(即,"_id": 1..但是如果它们是这样的"_id": ObjectId('1')

[
  {
    "_id": ObjectId('1'),
    "value": 50
  },
  .....
  .....
]
Run Code Online (Sandbox Code Playgroud)

那么你需要转换_idObjectId(obj._id)in update() 查询..所以你会这样做。

var ObjectId = require('mongodb').ObjectID;

idsArray.forEach(function(obj) {
   Model.update({_id: ObjectId(obj._id)}, {$set: {value: obj.value}});
});
Run Code Online (Sandbox Code Playgroud)

PS_id在继续之前确认它(即,)。

希望这可以帮助。

干杯,