2016-11-29 7 views
1

次はそれが私のデータベースにコレクションでどのように見えるかです:のMongoDB:特定の条件で更新複数のドキュメント

{ 
    row_num: 1, 
    value: 15 
} 
{ 
    row_num: 2, 
    value: 74 
} 
... 

今私は、次の更新JSONファイルを持っている:

{ 
    row_num: 1, 
    value: 16 
} 
{ 
    row_num: 2, 
    value: 28 
} 
... 

MongoDBのデータに1対1で対応します。私の質問は、MongoDB構文を使用して、スクリプト内のループを更新する代わりに、すべてのドキュメントの値を1行で更新できるかどうかです。

+0

あなたは、データベース内の文書を削除し、新しいものとそれを再挿入することができますか? – libik

+0

いいえできません。この例では、変更されない各ドキュメントの他のフィールドがあることを示していません。私はループを使わずに持っていたJSONファイルに従って、フィールド 'value'を変更したいだけです。 –

答えて

1

Bulk() APIを使用して、JSONアレイ内の各ドキュメントの更新要求をループで送信する代わりに、更新を行うことが可能です。これもまた は、バッチでサーバーに操作を送信する(たとえば、バッチサイズが500)ため、更新をより効率的かつ迅速に行うという点でパフォーマンスが向上しています。

次に、このアプローチを示し、最初の例では、MongoDBのバージョン> = 2.6及び< 3.2で利用可能Bulk() APIを使用します。これは、JSON内の1つの既存のvalueフィールドを変更することで、指定された配列から、コレクション内のすべての一致した文書を更新します。

var updatedJsonArray = [ 
    { "row_num": 1, "value": 16 }, 
    { "row_num": 2, "value": 28 }, 
    { "row_num": 3, "value": 43 }, 
    ... 
    { "row_num": 15478, "value": 9 } 
] 

MongoDBのバージョン> = 2.6と< 3.2

var bulk = db.collection.initializeUnorderedBulkOp(), 
    counter = 0; 

updatedJsonArray.forEach(function (doc) {  
    bulk.find({ "row_num": doc.row_num }).updateOne({ 
     "$set": { "value": doc.value } 
    }); 

    counter++; 
    if (counter % 500 === 0) { 
     // Execute per 500 operations 
     bulk.execute(); 
     // re-initialize every 500 update statements 
     bulk = db.collection.initializeUnorderedBulkOp(); 
    } 
}) 
// Clean up remaining queue 
if (counter % 500 !== 0) { bulk.execute(); } 

次の例は、deprecatedからBulk() APIまでの新しいMongoDBバージョン3.2に適用され、を使用して、新しいセットのAPIを提供しました

MongoDBのバージョン3.2以上

var ops = []; 
updatedJsonArray.forEach(function(doc) { 
    ops.push({ 
     "updateOne": { 
      "filter": { "row_num": doc.row_num }, 
      "update": { 
       "$set": { "value": doc.value } 
      } 
     } 
    }); 

    if (ops.length === 500) { 
     db.collection.bulkWrite(ops); 
     ops = []; 
    } 
}) 

if (ops.length > 0) 
    db.collection.bulkWrite(ops); 
関連する問題