这是复制我的问题的一个例子:
我用这样的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)
,服务器就在那里,从不回复。
简而言之,我要做的就是返回一个_id的列表,其中signUpDate不为null (应该有333,000左右)
我很确定问题是mongodb缓存的方式,但我不确定如何解决这个问题?
答案 0 :(得分:7)
您不应该像这样在大型结果集上调用toArray
。相反,要么:
使用each
:
collection.find({'signedUp': true}, {'_id':1}).each(function(err, doc){
if (doc) {
console.log(doc);
} else {
console.log('All done!');
}
});
或stream结果:
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!');
});
答案 1 :(得分:6)
您需要设置批量大小,然后流式传输或迭代结果,否则mongo驱动程序会将所有内容都粘贴到内存中。
同样{'_id':1}
闻起来很腥,可能应该是{fields: {'_id' : 1}}
因此,您的案例结果将是:
collection.find({'signedUp': true}, {batchSize: 1000, fields: {'_id' : 1}}).each(function(err, item) {
do something with item
});