2015-08-19 4 views
2

У меня есть коллекция 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); 
}); 

Любая помощь была бы высоко оценена!

+0

Ошибка при попытке выполнить вашу ошибку, вы видели [эту ошибку] ​​(http://askubuntu.com/a/503151), правильно? Во втором методе вы можете попробовать выполнить запрос между двумя временными метками: '{$ и: {{$ gte: currentDate}, {$ gte: currentDatePlusTwo}}}'. ([Индексация, похоже, путь] (http://askubuntu.com/a/503151)) – ippi

+0

Спасибо за ваше предложение с $ и! Однако это не совсем работает. Я получаю ошибку ** Ошибка: не могу использовать $ и с датой.** при использовании: _ {$ и: [{$ gte: currentDate}, {lte: currentDate}]} _ хотя. –

ответ

0

Я понял, что это своего рода.

мне удалось получить индекс работы с добавлением индекса к Mongoose схеме:

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); 
      } 
     });  
    } 
} 

Вышеуказанные работы с точностью до диапазона 14 дней между StartDate и EndDate, хотя она занимает около 20 секунд, чтобы работать даже с индексом.