ここでの問題は、実行しているループが各操作の完了を待機していないことです。つまり、実際には、数千の.save()
をキューに入れているだけです。 リクエストとそれらを同時に実行しようとしています。妥当な制限内でそれを行うことはできないため、エラー応答が返されます。
async モジュールには、そのイテレータのコールバックを処理しながら反復するためのさまざまなメソッドがあります。おそらく最も単純な直接の方法は、 。モデルは接続を認識しているため、Mongooseはコールバック内に埋め込む必要なしに、接続管理も処理します。
var tempColSchema = new Schema({
cid: {
type: Number,
required: true
},
loc:[]
});
var TempCol = mongoose.model( "TempCol", tempColSchema );
mongoose.connect( 'mongodb://localhost/mean-dev' );
var i = 0;
async.whilst(
function() { return i < 10000000; },
function(callback) {
i++;
var c = i;
console.log(c);
var lon = parseInt(c/100000);
var lat = c%100000;
new Tempcol({cid: Math.random(), loc: [lon, lat]}).save(function(err){
callback(err);
});
},
function(err) {
// When the loop is complete or on error
}
);
それを行うための最も素晴らしい方法ではありません。それでも一度に1回の書き込みであり、他の方法を使用して並行操作を「管理」することもできますが、少なくとも呼び出しスタックが爆発することはありません。
MongoDB 2.6以降では、 Bulk OperationsAPI を利用できます。 サーバー上で一度に複数の書き込みを処理するため。したがって、プロセスは似ていますが、今回は1回の書き込みと応答で一度に1000をサーバーに送信できます。これは、はるかに高速です。
var tempColSchema = new Schema({
cid: {
type: Number,
required: true
},
loc:[]
});
var TempCol = mongoose.model( "TempCol", tempColSchema );
mongoose.connect( 'mongodb://localhost/mean-dev' );
mongoose.on("open",function(err,conn) {
var i = 0;
var bulk = TempCol.collection.initializeOrderedBulkOp();
async.whilst(
function() { return i < 10000000; },
function(callback) {
i++;
var c = i;
console.log(c);
var lon = parseInt(c/100000);
var lat = c%100000;
bulk.insert({ "cid": Math.random(), "loc": [ lon, lat ] });
if ( i % 1000 == 0 ) {
bulk.execute(function(err,result) {
bulk = TempCol.collection.initializeOrderedBulkOp();
callback(err);
});
} else {
process.nextTick(callback);
}
},
function(err) {
// When the loop is complete or on error
// If you had a number not plainly divisible by 1000
if ( i % 1000 != 0 )
bulk.execute(function(err,result) {
// possibly check for errors here
});
}
);
});
これは実際にはマングースでまだ公開されていないネイティブドライバメソッドを使用しているため、接続が利用可能であることを確認するために追加の注意が払われています。これは例ですが、唯一の方法ではありませんが、要点は、接続用のマングースの「魔法」がここに組み込まれていないため、確立されていることを確認する必要があります。
処理するアイテムの数はラウンド数ですが、そうでない場合は、bulk.execute()
を呼び出す必要があります。 その最後のブロックでも示されていますが、モジュロに応答する数によって異なります。
重要な点は、操作のスタックを不当なサイズに拡大せず、処理を制限することです。ここでのフロー制御により、次の反復に進む前に実際に完了するまでに時間がかかる操作が可能になります。したがって、バッチ更新または追加の並列キューイングのいずれかが、最高のパフォーマンスを実現するために必要なものです。
.initializeUnorderedBulkOp()
もあります 書き込みエラーを致命的なものにしたくないが、代わりに別の方法でそれらを処理する場合は、このためのフォームを作成します。与えられた応答を解釈する方法については、ほとんどの場合、BulkAPIと応答に関する公式ドキュメントを参照してください。