Вопрос имеет более абстрактный и теоретический характер, даже скорее не вопрос, а рассуждение на тему.
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й, выпавшый вариант, он же является гатким утенком. Имея свой, весьма удобный язык запросов, уступает тройке в производительности, неся сие бремя яже довольно продолжительное время, и проблеска пока что ждать не приходится - со слов разработчикиков стараются, но у них не собо выходит.