Задать вопрос

Как правильно имплементировать пагинацию в MongoDB с сортировкой по compound индексу?

Вопрос имеет более абстрактный и теоретический характер, даже скорее не вопрос, а рассуждение на тему.


TLTR
Как правильно имплементировать пагинацию в MongoDB с сортировкой по compound индексу, а так же выборке по куче (~40 булевиков, чисел, строк, массивов) ключей? Предпологаемый размер коллекции 500K - 1M.

Про "шустрый" skip() и ranged queries знаю, но волею судеб они являются взаимоисключающими:
- запрос должен обрабатыватся максимально быстро (максимум по палате ~5ms) - прощай skip()
- результат должен иметь персистентность (пользователи имеют возможность делится результатами) - прощайте ranged queries

В первом случае, как не иронично, но самый логичный и "правильный" способ имеет "мелкие" проблемы с производительностью напрямую зависящие от количества "скипнутых" записей.
Пример:
// skip()
db.users
  .find({
    make: 'Mercedes-Benz',
    model: 'S 500/550'
    state: 'sale',
    arr: { $in: [ 'used', 'notDamaged' ] }
    mileage: { $lte: 80000 }
  })
  .sort({ priority: 1, age: -1, price: 1 })
  .skip(200) // уже показанные результаты
  .limit(25);


Во втором же, результат имеет крайнюю "хрупкость"- поле от которого зависит тот самый "промежуток". Удаление документа, редактирование одного из полей участвующих в выборке, изменение состояния влияющего на отображение в результатах - все ети факторы являются "смертельными" в вопросе персистентности.
Пример:
// Ranged query
db.users
  .find({
    _id: { $gt: lastId }, // _id последнего документа в последнем результате
    make: 'Mercedes-Benz',
    model: 'S 500/550'
    state: 'sale',
    arr: { $in: [ 'used', 'notDamaged' ] }
    mileage: { $lte: 80000 }
  })
  .sort({ priority: 1, age: -1, price: 1 })
  .limit(25);


Из предпологаемых выходов и данных разочарований ограничений, Я выделил пару наиболее реальных:
- построение своего, обычно "тяжелого", индекса по каждому типу запроса (типом может быть сортировка, ключевые ключи и т.д.) при помощи Redis/Memcached'а. Первым делом на ум приходит "тяжелый" Map/Reduce с инкрементальной (тут зависит от разработчика - желания/знаний/умений) перестройкой всего и вся.
- использование инной технологии (в моем случае иной NoSQL БД) - об етом ниже.

Самым реальным выходом для себя выбрал переход на другую NoSQL БД. Оных имеется весьма приличное количество но по свойствам сопоставимым с MongoDB Я отсановился на 3х:
- CouchDB - Map/Reduce и Views, при правильно построенном индексе весьма шустрая вещь, пагинация не является проблемой.
- Couchbase Server - детище выходцев проекта CouchDB, шустрее онного, open-source который не open-source (новые версии "запаздывают").
- Riak - пока ниччего не могу сказать, но большинство знакомых разоаботчиков крайне положительного мнения о ней.
- RethinkDB - 4й, выпавшый вариант, он же является гатким утенком. Имея свой, весьма удобный язык запросов, уступает тройке в производительности, неся сие бремя яже довольно продолжительное время, и проблеска пока что ждать не приходится - со слов разработчикиков стараются, но у них не собо выходит.
  • Вопрос задан
  • 3061 просмотр
Подписаться 6 Оценить Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы