2016-02-04 198 views
3

我想用不同的值更新多個文檔。貓鼬多更新

我的數據庫看起來像這樣。

[ 
    { 
     "_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 
     } 
    ] 

回答

3

首先所有update()查詢使用不好..

查看此文檔​​

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

假設當前的數據庫模型包含這樣的文檔(如你在問題描述爲好):

[ 
    { 
     "_id": 1, 
     "value": 50 
    }, 
    { 
     "_id": 2, 
     "value": 100 
    } 
]; 

,你已經低於其包含的對象數組(即,文檔)與當前數據庫的文檔進行修改,以這樣的:

idsArray: [ 
    { 
     "_id": 1, 
     "value": 4 
    }, 
    { 
     "_id": 2, 
     "value": 27 
    } 
]; 

從我用的MongoDB &貓鼬的經驗,我不認爲你可以更新單行查詢所有文檔(這就是你想做)......(PS,我不知道這件事,所以我不知道這個..)

但是,爲了使你的代碼的工作,你會做這樣的事情:

理念:遍歷文檔中的每個文檔即idsArray和通話更新()。

所以,這裏的代碼如下:

idsArray.forEach(function(obj) { 
    Model.update({_id: obj._id}, {$set: {value: obj.value}}); 
}); 

在上面的代碼中,我假設你已經在數據庫文檔_id值,因爲他們「上面(即"_id": 1)。但是,如果他們喜歡寫重這"_id": ObjectId('1')

[ 
    { 
    "_id": ObjectId('1'), 
    "value": 50 
    }, 
    ..... 
    ..... 
] 

那麼您會發現需要_id轉換爲ObjectId(obj._id)的更新()查詢.. 所以,你會做這樣的。

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

idsArray.forEach(function(obj) { 
    Model.update({_id: ObjectId(obj._id)}, {$set: {value: obj.value}}); 
}); 

P.S.在前進之前確認它(即_id)。

希望這有助於您。

乾杯,

+0

我以前嘗試過類似的東西,我循環通過我的價值觀。我的問題是,如果我採取這種方法,我在哪裏設置res.end();因爲如果我在foreach結束後設置res.end(),我仍然有一堆回調等待我的Model.update完成。 – user3862830

+0

通過回調(我猜) - 嘗試做一個func函數(回調){callback();}'更新數據庫中的所有文檔並將回調函數返回到主函數中,在那裏你將完成你的工作;只是嘗試這種方式。 – narainsagar

+0

一個函數(比如:'callbackFunc'),它會更新你的所有文檔,然後從被調用的地方返回回調(假設:'mainFunc'),這意味着你的所有文檔將被更新(意味着callbackFunc完成),那麼你會/調用'res.end()' – narainsagar

1

多更新只用於更新多個文檔爲相同的值(一個或多個)或同一update operation對所有文檔的更新都可以使用。

如果你想更新到不同的值,你必須使用幾個更新語句。

6

假設你有對象的數組,你想在您的收藏更新匹配的IDS像

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獲得更好的性能優勢。對於支持MongoDB Server 3.2.x, 的Mongoose版本>=4.3.0,您可以使用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); 

對於貓鼬版本~3.8.8, ~3.8.22, 4.x支持MongoDB的服務器>=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 
    }); 
}