Проекции, сортировка и пагинация
Как вернуть только нужные поля, упорядочить результат и разбить его на страницы.
Проекция — это указание, какие поля документа включить в ответ или исключить из него.
Проекция: только нужные поля
По умолчанию find возвращает документы целиком. Часто это лишнее: приложению нужны два-три поля, а не весь объект. Вторым аргументом find передают проекцию — 1 включает поле, 0 исключает:
db.users.find(
{ city: "Казань" },
{ name: 1, age: 1 }
)Вернутся только name, age — и _id, который попадает в проекцию автоматически. Чтобы его убрать, исключите явно:
db.users.find(
{ city: "Казань" },
{ name: 1, age: 1, _id: 0 }
)Правило: в одной проекции нельзя смешивать включение (1) и исключение (0) полей — кроме _id, который можно отключать в любом случае. Либо перечисляете, что оставить, либо что убрать.
Сортировка: sort
Метод sort выстраивает результат: 1 — по возрастанию, -1 — по убыванию. Сначала самые молодые:
db.users.find().sort({ age: 1 })Сортировать можно по нескольким полям — порядок ключей задаёт приоритет. Сначала по городу (А→Я), внутри города — по убыванию возраста:
db.users.find().sort({ city: 1, age: -1 })limit и skip: пагинация
limit ограничивает число документов в ответе, skip пропускает первые N. Вместе они дают постраничную выдачу. Топ-3 самых старших пользователя:
db.users.find().sort({ age: -1 }).limit(3)Вторая страница по 10 записей (пропускаем первые 10, берём следующие 10):
db.users.find()
.sort({ age: -1 })
.skip(10)
.limit(10)Методы — это звенья одной цепочки (она называется курсором): база применяет сначала фильтр, затем сортировку, затем skip и limit. Поэтому sort почти всегда ставят перед пагинацией — иначе «страницы» будут произвольными.
Осторожно с большими skip
На больших коллекциях skip на десятки тысяч записей работает медленно: база всё равно перебирает пропускаемые документы. Для глубокой пагинации в продакшене используют приём «по последнему _id» (range-пагинация) вместо больших skip. Для учебных объёмов skip/limit вполне годятся.
Итог
- Проекция (
1/0) отдаёт только нужные поля; нельзя смешивать включение и исключение, кроме_id. sort({ поле: 1 })— по возрастанию,-1— по убыванию; можно по нескольким полям.limit+skipдают пагинацию;sortставят до них, а большихskipизбегают на проде.