Mongoose multi update

后端 未结 3 907
囚心锁ツ
囚心锁ツ 2021-02-10 16:26

I want to update multiple docs with different values.

My Database looks something like this.

[
    {
        \"_id\": 1,
        \"value\": 50
    },
            


        
3条回答
  •  小鲜肉
    小鲜肉 (楼主)
    2021-02-10 16:59

    Supposing you had an array of objects that you wanted to update in your collection on matching ids like

    var soldItems = [
            {
                "_id": 1,
                "value": 4
            },
            {
                "_id": 2,
                "value": 27
            }
        ];
    

    then you could use the forEach() method on the array to iterate it and update your collection:

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

    or use promises as

    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);
    });
    

    or using 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);
    }); 
    

    For larger arrays, you could take advantage of using a bulk write API for better performance. For Mongoose versions >=4.3.0 which support MongoDB Server 3.2.x, you can use bulkWrite() for updates. The following example shows how you can go about this:

    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);
    

    For Mongoose versions ~3.8.8, ~3.8.22, 4.x which support MongoDB Server >=2.6.x, you could use the Bulk API as follows

    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
        });
    }
    

提交回复
热议问题