我有一个名为'价格'的MongoDB系列。我试图查询“开始日期”和“开始日期”之间的价格。和' 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}}
如果我删除了排序(' -timestamp")行,并再次运行此查询,则会出现以下错误:
GET /prices/graph/minute - - ms - -
FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - process out of memory
我也尝试在此查询中使用索引来尝试避免32MB的内存排序限制,但是还没有能够实现它。我想知道它是否是由问题造成的:
"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()
然而,这种方法不起作用,似乎对于循环的每次迭代&#39; currentDate&#39; =&#39; startDate&#39;所以它只是在“开始日期”之前查询数据库中记录的最后价格。
编辑:方法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);
});
非常感谢任何帮助!
答案 0 :(得分:0)
我想出了这个。
我设法通过向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秒。