2016-10-14 23 views
1

私はdb asを持っていると仮定します。コレクションの値を更新する方法

{ name: "alex" , id: "1"} 

コレクションを更新します。私は "Mr."を追加したいnameフィールドの値に設定します。

{ name: "Mr.alex" , id: "1"} 

どうすればいいですか?私は2つのクエリを書かなければならない。

db.collection("user").find({id : "1"}).toArray(function(err, result){ 
    var name = result[0].name; 
    db.collection("user").updateOne({id : "1"}, {name: "Mr." + name},function(err, result){ 

    }) 
}) 

そこにMongoDBにx = x+1としてこれを行うに任意のより良い方法はありませんか?

答えて

0

AFAIK 2つのクエリがあります。更新演算子はフィールドの値を取らず、値を提供する必要があります。

ただし、すべてのドキュメントまたは大量のドキュメントに対して行う必要がある場合は、スクリプトを作成してカーソルを各ドキュメントに対して使用し、ドキュメントごとに名前を変更し、引数を渡してdb.user.saveユーザオブジェクト。

ボトムラインは同じです。

0

は、以下試してください。

var cursor = db.users.find({}); 
while (cursor.hasNext()) { 
    var user = cursor.next(); 
    user.name = "Mr." + user.name; 
    user.save(); 

} 

が可能1つのクエリを使用していません。ドキュメントを繰り返し処理し、更新された結果を保存する必要があります。

0

現在、同じクエリ内で取得したドキュメントを参照する方法はなく、同じ操作内でドキュメントを検索して更新することはできません。

したがって、あなたが探しているものを達成するために複数のクエリを作成する必要があります。

/* 
* Single Document 
*/ 

// I'm assuming the id field is unique and can only return one document 
var doc = db.collection('user').findOne({ id: '1' }); 

try { 
    db.collection('user').updateOne({ id: '1' }, { $set: { name: 'Mr. ' + doc.name }}); 
} catch (e) { 
    print(e); 
} 

あなたが複数の更新操作を処理したい場合は、Bulk()操作ビルダーを使用して行うことができます。

/* 
* Multiple Documents 
*/ 
var bulk = db.collection('user').initializeUnorderedBulkOp(); 

// .forEach is synchronous in MongoDB, as it performs I/O operations 
var users = db.collection('user').find({ id: { $gt: 1 } }).forEach(function(user) { 
    bulk.find({ id: user.id }).update({ $set: { name: 'Mr. ' + user.name }}); 
}); 

bulk.execute(); 
0

既存のフィールドでコレクションを更新するための鍵は、配列をループしているfind().toarray()カーソルメソッドから返され、使用してあなたのコレクションを更新Bulk APIこれにより、1回のリクエスト(バッチとして)内で多くの更新操作を送信できます。


のはこれが出てペンどのようにいくつかの例を見てみましょう:

A)のMongoDBサーバのバージョン3.2および上記で

db.collection("user").find({id : "1"}).toArray(function(err, result){ 
    var operations = []; 
    result.forEach(function(doc){ 
     operations.push({ 
      "updateOne": { 
       "filter": { 
        "_id": doc._id, 
        "name": doc.name 
       }, 
       "update": { 
        "$set": { "name": "Mr." + doc.name } 
       } 
      } 
     }); 

     // Send once in 500 requests only 
     if (operations.length % 500 === 0) { 
      db.collection("user").bulkWrite(operations, function(err, r) { 
       // do something with result 
      } 
      operations = []; 
     } 

    }); 

    // Clear remaining queue 
    if (operations.length > 0) { 
     db.collection("user").bulkWrite(operations, function(err, r) { 
      // do something with result 
     } 
    } 
}) 

上記の場合は、あなたがあなたの操作を初期化するだろう配列Bulk APIのbulkWrite()関数で使用され、更新操作を保持します。

カーソル関数からの結果は、更新オブジェクトを使用して操作配列を作成するために反復されます。操作は500のバッチに制限されています。

デフォルトのバッチ制限の1000より低い値を選択するのは、一般的に制御された選択です。そこに書かれているように、MongoDBはデフォルトで0xに送信されます。したがって、これらのデフォルトの1000操作要求が実際に16MB BSON limitに収まることを保証する保証はありません。

したがって、サーバーに送信する際のデータの制限よりも少ない合計サイズになるように、効果的にしか管理できない低い「バッチサイズ」を課す必要があります。

// Get the collection 
var col = db.collection('user'); 
// Initialize the unordered Batch 
var batch = col.initializeUnorderedBulkOp(); 
// Initialize counter 
var counter = 0; 

col.find({id : "1"}).toArray(function(err, result){ 
    result.forEach(function(doc) { 
     batch.find({ 
      "_id": doc._id, 
      "name": doc.name 
     }).updateOne({ 
      "$set": { "name": "Mr. " + doc.name } 
     }); 
     counter++; 

     if (counter % 500 === 0) { 
      batch.execute(function(err, r) { 
       // do something with result       
      }); 
      // Re-initialize batch 
      batch = col.initializeOrderedBulkOp(); 
     }   
    }); 

    if (counter % 1000 != 0){ 
     batch.execute(function(err, r) { 
      // do something with result       
     }); 
    } 
}); 


A)以下のMongoDB V3.0またはを使用している場合

関連する問題