У меня есть коллекция MongoDB под названием «Цены», в которой я пытаюсь запросить цены между «startDate» и «endDate».MongoDB Querying Large Collections
Коллекция хранит цены каждые 10 секунд, однако при запросе этой коллекции для целей графического отображения важна только цена каждые 1-2 минуты.
Я попытался написать этот запрос двумя различными способами:
Метод 1: Использование {$ GTE: STARTDATE, $ Ге: 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}}
Если удалить вид ('- временная метка ") строку и запустить этот запрос еще раз я получаю следующее сообщение об ошибке:
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 Loop для запроса thte Последней цены каждого 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».
Редактировать: Метод 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);
});
Любая помощь была бы высоко оценена!
Ошибка при попытке выполнить вашу ошибку, вы видели [эту ошибку] (http://askubuntu.com/a/503151), правильно? Во втором методе вы можете попробовать выполнить запрос между двумя временными метками: '{$ и: {{$ gte: currentDate}, {$ gte: currentDatePlusTwo}}}'. ([Индексация, похоже, путь] (http://askubuntu.com/a/503151)) – ippi
Спасибо за ваше предложение с $ и! Однако это не совсем работает. Я получаю ошибку ** Ошибка: не могу использовать $ и с датой.** при использовании: _ {$ и: [{$ gte: currentDate}, {lte: currentDate}]} _ хотя. –