2015-09-07 25 views
8

条件付きでMongoに挿入することは可能ですか?私は、単一の挿入を行う場合MongoDB-存在しない場合は挿入、そうでない場合は

//Pseudo code 

Bulk Insert Item : 

If Key exists 
    Skip, don't throw error 
If key does not exist 
    Add item 

、それがエラーを返すか、コレクションに挿入し、それがバルクで可能であるかもしれませんか?

+0

読む[「アップサート」](HTTP://docs.mongodb。 org/manual/reference/method/db.collection.update /#upsert-option)を参照してください。これがMongoDBのやり方です。バルク操作に必要な修飾子として '.upsert()'があります。また、['$ setOnInsert'](http://docs.mongodb.org/manual/reference/operator/update/setOnInsert/)は、新しい文書が"挿入 "されている場合にのみ変更を適用し、唯一の操作がある場合は変更しませんそのブロック。 –

答えて

12

あなたは物事を処理する方法に応じて、ここでは二つの実の選択肢があります。MongoDBのの

  1. 使用upsert機能キーデータが存在する場合、基本的に「検索」へ。そうでなければ、データは$setOnInsertにしか渡されず、それ以外のものには触れません。

  2. バルクで「非操作」操作を使用します。エラーが返されても更新プログラムのバッチはすべて継続されますが、エラーレポートはそのままで、エラーではないものはすべて完了します。

全体の例:現在のドライバで「変更されたアクションは、」以前のリリースがなかったどこ.execute()の結果応答が、スローされるエラーオブジェクトを返すことであることを

var async = require('async'), 
    mongoose = require('mongoose'), 
    Schema = mongoose.Schema; 

var testSchema = new Schema({ 
    "_id": Number, 
    "name": String 
},{ "_id": false }); 

var Test = mongoose.model('Test',testSchema,'test'); 

mongoose.connect('mongodb://localhost/test'); 

var data = [ 
    { "_id": 1, "name": "One" }, 
    { "_id": 1, "name": "Another" }, 
    { "_id": 2, "name": "Two" } 
]; 

async.series(
    [ 
    // Start fresh 
    function(callback) { 
     Test.remove({},callback); 
    }, 

    // Ordered will fail on error. Upserts never fail! 
    function(callback) { 
     var bulk = Test.collection.initializeOrderedBulkOp(); 
     data.forEach(function(item) { 
     bulk.find({ "_id": item._id }).upsert().updateOne({ 
      "$setOnInsert": { "name": item.name } 
     }); 
     }); 
     bulk.execute(callback); 
    }, 

    // All as expected 
    function(callback) { 
     Test.find().exec(function(err,docs) { 
     console.log(docs) 
     callback(err); 
     }); 
    }, 


    // Start again 
    function(callback) { 
     Test.remove({},callback); 
    }, 

    // Unordered will just continue on error and record an error 
    function(callback) { 
     var bulk = Test.collection.initializeUnorderedBulkOp(); 
     data.forEach(function(item) { 
     bulk.insert(item); 
     }); 
     bulk.execute(function(err,result) { 
     callback(); // so what! Could not care about errors 
     }); 
    }, 


    // Still processed the whole batch 
    function(callback) { 
     Test.find().exec(function(err,docs) { 
     console.log(docs) 
     callback(err); 
     }); 
    } 
    ], 
    function(err) { 
    if (err) throw err; 
    mongoose.disconnect(); 
    } 
); 

注意「順序付けられていない」操作でそうする。

これはコードがerrに依存することは絶対に避けてください。エラーの完全な分類ではなく、返されたresultを使用してください。

しかし、順序付けされていない場合、エラーの発生数に関係なく、バッチは最後まで続きます。エラーではないものは正常にコミットされます。

これは実際には「シーケンスが重要です」となります。その場合は、 "順序付けられた"操作が必要で、 "アップセレット"を使用することで重複するキーのみを避けることができます。それ以外の場合は「順序なし」を使用しますが、エラーの戻り値と実際の意味を理解しておいてください。

.collectionを使用して、基本ドライバから基本的なコレクションオブジェクトを取得して「一括」操作を有効にする場合は、必ず「いくらか」のmongooseメソッドが常に最初に呼び出されていることを確認してください。

これがなければ、mongooseメソッドで処理されるネイティブドライバメソッドによるデータベースへの接続は保証されないため、接続がないために操作が失敗します。

代替が最初マングース方法を「発射」する、接続のためのイベントリスナーでアプリのロジックをラップすることです:

mongoose.connection.on("open",function(err) { 
    // app logic in here 
}) 
+1

恐ろしい!ありがとうございました –

関連する問題