2

これは私の問題を再現する例です:

コレクションに次のような100万のドキュメントを入力します。

for(i=1; i<=1000000; i++){
if(i%3===0)
     db.numbers.insert({_id:i, stuff:"Some data", signUpDate: new Date()});
else
     db.numbers.insert({_id:i, stuff:"Some data"});
}

したがって、3番目のドキュメントごとにsignUpDateがあります

次のインデックスを作成します。

db.numbers.ensureIndex({"signUpDate" : 1});

次に、nodejsを使用した次の非常に小さなアプリがあります。

var Db = require('mongodb').Db
, Connection = require('mongodb').Connection
, Server = require('mongodb').Server
, format = require('util').format;

var host = 'localhost';
var port = Connection.DEFAULT_PORT;

console.log("Connecting to " + host + ":" + port);

Db.connect(format("mongodb://%s:%s/test?w=1", host, port), function(err, db) {
        var collection = db.collection('numbers');

        collection.find({'signedUp': true}, {'_id':1}).limit(100000).toArray(function(err, docs){
                console.log(docs.length)
        });
});

これは正常に機能します。

ただし、を削除する .limit(100000)と、サーバーはそこにとどまり、応答しなくなります。

一言で言えば、私がやろうとしているのは、signUpDateがnullではない_idのリストを返すことだけです(約333,000あるはずです)

問題はmongodbがキャッシュする方法であると確信していますが、これを回避する方法がわかりません。

4

2 に答える 2

7

toArrayこのような大きな結果セットを呼び出すべきではありません。代わりに、次のいずれかを行います。

を使用して結果を繰り返しますeach

collection.find({'signedUp': true}, {'_id':1}).each(function(err, doc){
    if (doc) {
        console.log(doc);
    } else {
        console.log('All done!');
    }
});

または結果をストリーミングします。

var stream = collection.find({'signedUp': true}, {'_id':1}).stream();
stream.on('data', function(doc) {
    console.log(doc);
});
stream.on('close', function() {
    console.log('All done!');
});
于 2012-12-05T15:21:58.207 に答える
6

バッチサイズを設定してから、結果をストリーミングまたは反復する必要があります。そうしないと、mongoドライバーがすべてをメモリに貼り付けます。

また{'_id':1}、それは魚臭いにおいがします、それはおそらくあるべきです{fields: {'_id' : 1}}

したがって、あなたの場合の結果は次のようになります。

collection.find({'signedUp': true}, {batchSize: 1000, fields: {'_id' : 1}}).each(function(err, item) { 
    do something with item
});
于 2012-12-05T15:23:23.253 に答える