マングース(mongodb)バッチ挿入?


114

DOES マングースのV3.6 +今のサポートバッチ挿入?私は数分間検索しましたが、このクエリに一致するものはすべて数年前のものであり、答えは明確なノーでした。

編集:

今後の参考のために、答えはを使用することModel.create()です。create()最初の引数として配列を受け入れるため、挿入するドキュメントを配列として渡すことができます。

Model.create()のドキュメントを参照してください


前の質問に対するこの回答を参照してください。
JohnnyHK 2013年

ありがとう。それが、投稿後に見つけたものです。
Geuis 2013年

@Geuisは編集内容を回答として追加し、それを受け入れて質問を解決してください。
FilipDupanović2014年


Model.create()は遅いため、大量のドキュメントを挿入することを検討している場合は、代わりにこのアプローチを採用することをお勧めします。
Lucio Paiva、2015年

回答:


162

Model.create()とModel.collection.insert()の比較:より高速なアプローチ

Model.create()非常に大きなバルクを処理している場合、挿入を行うには不適切な方法です。そうなる非常に遅いです。その場合はModel.collection.insertより優れたパフォーマンスのを使用する必要があります。バルクのサイズにModel.create()もよりますが、クラッシュもします!100万件のドキュメントを試したが、運がなかった。Model.collection.insertそれを使用すると、ほんの数秒かかりました。

Model.collection.insert(docs, options, callback)
  • docs 挿入するドキュメントの配列です。
  • optionsオプションの設定オブジェクトです- ドキュメントを参照してください
  • callback(err, docs)すべてのドキュメントが保存されるか、エラーが発生した後に呼び出されます。成功した場合、docsは永続化されたドキュメントの配列です。

Mongooseの作者がここで指摘しているように、このメソッドは検証手順をバイパスし、Mongoドライバに直接アクセスします。大量のデータを処理するため、トレードオフになります。そうしないと、データベースにデータを挿入できなくなります(ここでは何十万ものドキュメントについて話していることに注意してください)。

簡単な例

var Potato = mongoose.model('Potato', PotatoSchema);

var potatoBag = [/* a humongous amount of potato objects */];

Potato.collection.insert(potatoBag, onInsert);

function onInsert(err, docs) {
    if (err) {
        // TODO: handle error
    } else {
        console.info('%d potatoes were successfully stored.', docs.length);
    }
}

2019-06-22を更新insert()引き続き問題なく使用できますが、非推奨になりましたinsertMany()。パラメータはまったく同じなので、ドロップイン置換として使用するだけで、すべてが正常に機能するはずです(まあ、戻り値は少し異なりますが、おそらく使用していません)。

参照



マングースの例を挙げてください。
Steve K

15
Model.collectionMongoドライバーを直接経由するため、検証とフックを含むすべてのきちんとしたマングースのものが失われます。心に留めておくべきこと。Model.createフックを失いますが、まだ検証を通過しています。すべてが必要な場合は、反復処理を行う必要がありますnew MyModel()
Pier-Luc Gendreau '12

1
@ Pier-LucGendreauまったくそのとおりですが、膨大な量のデータを処理し始めたら、それはトレードオフです。
Lucio Paiva、2015年

1
新しいリーダーに注意してください:「バージョン2.6で変更:insert()は操作のステータスを含むオブジェクトを返します」。これ以上のドキュメントはありません。
Mark Ni

117

Mongoose 4.4.0が一括挿入をサポート

Mongoose 4.4.0では、モデルメソッドに--true--一括挿入が導入されてい.insertMany()ます。ループする.create()か、配列を提供するよりもはるかに高速です。

使用法:

var rawDocuments = [/* ... */];

Book.insertMany(rawDocuments)
    .then(function(mongooseDocuments) {
         /* ... */
    })
    .catch(function(err) {
        /* Error handling */
    });

または

Book.insertMany(rawDocuments, function (err, mongooseDocuments) { /* Your callback function... */ });

あなたはそれを追跡することができます:


2
現在、このメソッドはオプションをサポートしていません。
Amri 2016年

答えてくれてありがとう。rawDocumentsをどのように構文解析する必要があるか、何か考えはありますか?私はJsonオブジェクトの配列で試してみましたが、挿入されたのはそれらのIDだけでした。:(
Ondrej Tokar

4
これはどう違うのbulkWriteですか?ここを参照してください:stackoverflow.com/questions/38742475/...
オンドレイTokar

insertManyは動作しません。を手に入れましたfatal error allocation failed。しかし、collection.insertを使用すると、完全に機能します。
John

これは、マングーススキーマが提供する追加機能で機能しますか?exは、日付が存在しない場合にデータを追加しますdateCreated : { type: Date, default: Date.now },
ジャックブランク

22

実際、Mongooseの「作成」メソッドを使用できます。これには、ドキュメントの配列を含めることができます。次の例を参照してください。

Candy.create({ candy: 'jelly bean' }, { candy: 'snickers' }, function (err, jellybean, snickers) {
});

コールバック関数には、挿入されたドキュメントが含まれています。挿入する必要がある項目の数が常にわからない(上記のように固定長の引数)ため、それらをループ処理できます。

var insertedDocs = [];
for (var i=1; i<arguments.length; ++i) {
    insertedDocs.push(arguments[i]);
}

更新:より良いソリューション

Candy.collection.insert()代わりにCandy.create()- より良いソリューションを使用することをお勧めします-上記の例で使用されている-高速であるためです(各項目をcreate()呼び出すModel.save()ので低速です)。

詳細については、Mongoのドキュメントを参照してください:http : //docs.mongodb.org/manual/reference/method/db.collection.insert/

(これを指摘してくれたarcseldonに感謝)


groups.google.com/forum/#!topic/mongoose-orm/IkPmvcd0kds-必要に応じて、リンクにはより適切なオプションがあります。
arcseldon 2014

あなたが意味するものではありません。{type:'jellybean'}代わりに{type:'jelly bean'}?ところで それらはどんな奇妙なタイプですか?それらはMongoose APIの一部ですか?
スティーブK

2
まあ、それは悪い名前の選択です。なぜなら、type通常、MongooseではデータベースオブジェクトのADTを指定するために予約されているからです。
Steve K

2
@sirbenbenji変更しましたが、公式ドキュメントにもある例です。私はこれに反対投票する必要はなかったと思います。
benske '19

1
.collectionプロパティをアドレス指定することで、Mongooseをバイパスしています(検証、「事前」メソッド...)
Derek

4

配列に値を挿入することで、mongoDBシェルを使用して一括挿入を実行できます。

db.collection.insert([{values},{values},{values},{values}]);

マングースで一括挿入する方法はありますか?
サンダラジャンK 2014

1
YourModel.collection.insert()
Bill Dami 2014年

.collectionプロパティをアドレス指定することで、Mongooseをバイパスしています(検証、「事前」メソッド...)
Derek

これはマングースではなく、生のcollection.insert答えはこの答えの数週間前に与えられ、より詳細に説明されました。
Dan Dascalescu

4

最高スコアの回答として、マングースを使用して一括挿入を実行できます。しかし、この例は機能しません。次のようにする必要があります。

/* a humongous amount of potatos */
var potatoBag = [{name:'potato1'}, {name:'potato2'}];

var Potato = mongoose.model('Potato', PotatoSchema);
Potato.collection.insert(potatoBag, onInsert);

function onInsert(err, docs) {
    if (err) {
        // TODO: handle error
    } else {
        console.info('%d potatoes were successfully stored.', docs.length);
    }
}

一括挿入にはスキーマインスタンスを使用しないでください。プレーンマップオブジェクトを使用する必要があります。


最初の答えは間違いではなく、検証されているだけです
Luca Steeb '18

1
.collectionプロパティをアドレス指定することで、Mongooseをバイパスしています(検証、「事前」メソッド...)
Derek

4

insertManyでデータを保存する方法と保存する方法の両方を以下に示します

1)Mongooseはドキュメントの配列をinsertManyまとめて保存します

/* write mongoose schema model and export this */
var Potato = mongoose.model('Potato', PotatoSchema);

/* write this api in routes directory  */
router.post('/addDocuments', function (req, res) {
    const data = [/* array of object which data need to save in db */];

    Potato.insertMany(data)  
    .then((result) => {
            console.log("result ", result);
            res.status(200).json({'success': 'new documents added!', 'data': result});
    })
    .catch(err => {
            console.error("error ", err);
            res.status(400).json({err});
    });
})

2)Mongooseでドキュメントの配列を保存 .save()

これらのドキュメントは並行して保存されます。

/* write mongoose schema model and export this */
var Potato = mongoose.model('Potato', PotatoSchema);

/* write this api in routes directory  */
router.post('/addDocuments', function (req, res) {
    const saveData = []
    const data = [/* array of object which data need to save in db */];
    data.map((i) => {
        console.log(i)
        var potato = new Potato(data[i])
        potato.save()
        .then((result) => {
            console.log(result)
            saveData.push(result)
            if (saveData.length === data.length) {
                res.status(200).json({'success': 'new documents added!', 'data': saveData});
            }
        })
        .catch((err) => {
            console.error(err)
            res.status(500).json({err});
        })
    })
})

3

mongooseを使用すると、使用するときに1000以上のドキュメントの制限があるようです

Potato.collection.insert(potatoBag, onInsert);

以下を使用できます。

var bulk = Model.collection.initializeOrderedBulkOp();

async.each(users, function (user, callback) {
    bulk.insert(hash);
}, function (err) {
    var bulkStart = Date.now();
    bulk.execute(function(err, res){
        if (err) console.log (" gameResult.js > err " , err);
        console.log (" gameResult.js > BULK TIME  " , Date.now() - bulkStart );
        console.log (" gameResult.js > BULK INSERT " , res.nInserted)
      });
});

しかし、これは10000のドキュメントでテストする場合、ほぼ2倍高速です。

function fastInsert(arrOfResults) {
var startTime = Date.now();
    var count = 0;
    var c = Math.round( arrOfResults.length / 990);

    var fakeArr = [];
    fakeArr.length = c;
    var docsSaved = 0

    async.each(fakeArr, function (item, callback) {

            var sliced = arrOfResults.slice(count, count+999);
            sliced.length)
            count = count +999;
            if(sliced.length != 0 ){
                    GameResultModel.collection.insert(sliced, function (err, docs) {
                            docsSaved += docs.ops.length
                            callback();
                    });
            }else {
                    callback()
            }
    }, function (err) {
            console.log (" gameResult.js > BULK INSERT AMOUNT: ", arrOfResults.length, "docsSaved  " , docsSaved, " DIFF TIME:",Date.now() - startTime);
    });
}

1
.collectionプロパティをアドレス指定することで、Mongooseをバイパスしています(検証、「事前」メソッド...)
Derek

0

私たちのプロジェクトからの機能し、関連するコードを共有する:

//documentsArray is the list of sampleCollection objects
sampleCollection.insertMany(documentsArray)  
    .then((res) => {
        console.log("insert sampleCollection result ", res);
    })
    .catch(err => {
        console.log("bulk insert sampleCollection error ", err);
    });

.insertManyソリューションは、すでに与えられた(と説明)この中にされた2016年の答え
Dan Dascalescu
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.