Недавно я столкнулся с той же проблемой при попытке разбить запрос на страницы при использовании поля, которое не было уникальным, например «FirstName». Идея этого запроса состоит в том, чтобы иметь возможность реализовать разбиение на страницы в неуникальном поле без использования skip ()
Основной проблемой здесь является возможность запроса поля, которое не является уникальным "FirstName", потому что произойдет следующее:
- $ gt: {"FirstName": "Carlos"} -> это пропустит все записи, где имя "Carlos"
- $ gte: {"FirstName": "Carlos"} -> всегда будет возвращать один и тот же набор данных
Поэтому решение, которое я нашел, заключалось в том, чтобы сделать часть запроса $ match уникальной, объединив поле целевого поиска со вторичным полем, чтобы сделать его уникальным поиском.
По возрастанию:
db.customers.aggregate([
{$match: { $or: [ {$and: [{'FirstName': 'Carlos'}, {'_id': {$gt: ObjectId("some-object-id")}}]}, {'FirstName': {$gt: 'Carlos'}}]}},
{$sort: {'FirstName': 1, '_id': 1}},
{$limit: 10}
])
По убыванию:
db.customers.aggregate([
{$match: { $or: [ {$and: [{'FirstName': 'Carlos'}, {'_id': {$gt: ObjectId("some-object-id")}}]}, {'FirstName': {$lt: 'Carlos'}}]}},
{$sort: {'FirstName': -1, '_id': 1}},
{$limit: 10}
])
Часть $ match этого запроса в основном ведет себя как оператор if:
если firstName - "Карлос", то он также должен быть больше, чем этот идентификатор
если firstName не равно "Carlos", тогда оно должно быть больше, чем "Carlos"
Единственная проблема заключается в том, что вы не можете перейти к определенному номеру страницы (это, вероятно, можно сделать с помощью некоторых манипуляций с кодом), но кроме этого он решил мою проблему с разбиением на страницы для неуникальных полей без необходимости использовать пропуск, который съедает много памяти и вычислительной мощности при завершении работы с любым набором данных, к которому вы обращаетесь.