MongoDB查询大集合
我有一个名为“价格”的MongoDB集合,我试图查询“startDate”和“endDate”之间的价格。
该系列产品每隔10秒钟就会储存一次价格,但是当查询这个系列产品时,每1-2分钟价格就非常重要。
我试图用两种不同的方式来写这个查询:
方法1:使用{$ gte:startDate,$ lte:endDate}
function getResultsInRange(startDate, endDate) { if(typeof startDate !== 'undefined' && typeof endDate !== 'undefined') { Price.find({timestamp: {$gte: startDate, $lte: endDate}}, 'price timestamp exchange') .sort('-timestamp') // .populate('exchange') .exec(function(err, prices) { if(err) { res.jsonp({'error': err}); } else { console.log("Found: " + prices.length + " prices"); res.jsonp(prices); } }); } }
此方法引发以下错误:
{"error":{"name":"MongoError","$err":"Executor error: Overflow sort stage buffered data usage of 33554490 bytes exceeds internal limit of 33554432 bytes","code":17144}}
如果我删除sorting(' – timestamp“)行,并再次运行此查询,我得到以下错误:
GET /prices/graph/minute - - ms - - FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - process out of memory
我也尝试过在这个查询中使用索引来试图避免32MB的内存sorting限制,但一直没有能够实现。 我想知道是否是由这个问题引起的:
"The total size of an index entry, which can include structural overhead depending on the BSON type, must be less than 1024 bytes."
这里描述:( http://docs.mongodb.org/manual/reference/limits/#indexes )
方法2:使用While循环来查询每个X分钟的最后价格(例如2)
function getResultsInRange(startDate, endDate) { if(typeof startDate !== 'undefined' && typeof endDate !== 'undefined') { var currentDate = startDate; currentDate.setSeconds(0); var priceData = {}; while(currentDate < endDate) { Price.findOne({'timestamp': {$lte: currentDate}}, 'price timestamp exchange') .sort('-timestamp') .exec(function(err, price) { if(err) { console.log('ERROR: ' + err); } else if (price !== null) { // PUSH DATA TO ARRAY HERE } }); // Increment Current Date. currentDate.setMinutes(currentDate.getMinutes() + 2); } res.jsonp(priceData); }//end if startDate and endDate are defined (giving us a valid date range). }// end getResultsInRange()
然而,这种方法不起作用,对于循环currentDate'='startDate'的每一次迭代,似乎只是在'startdate'之前查询数据库中logging的最后一个价格。
编辑:方法3:使用stream()我也尝试使用.stream()。
var query = Price.find({timestamp: {$gte: startDate, $lte: endDate}}, 'price timestamp exchange').populate('exchange').stream(); query.on('data', function(price) { // ADD TO ARRAY }).on('error', function(err) { console.log("ERROR: " + err); }).on('close', function() { res.jsonp(priceData); });
任何帮助将非常感激!
我明白了这一点。
我设法通过向Mongoose Schema添加一个索引来处理索引:
timestamp: { type: Date, index: true, default: Date.now },
然后使用下面的函数来执行查询。
function getResultsInRange(startDate, endDate) { if(typeof startDate !== 'undefined' && typeof endDate !== 'undefined') { Price.find({timestamp: {$gte: startDate, $lte: endDate}}, 'price timestamp exchange') .sort('-timestamp') .populate('exchange') .exec(function(err, prices) { if(err) { res.jsonp({'error': err}); } else { res.jsonp(prices); } }); } }
以上的工作可以在startDate和endDate之间达到14天的范围,即使索引运行也需要大约20秒的时间。