3. Запросы и выборка

В главе 1 мы вкратце рассмотрели команду find. Однако, find — это не только селекторы. Как уже упоминалось, результатом find является курсор. Пришло время рассмотреть это детальнее.

Выбор полей

Прежде чем переходить к курсорам, следует знать, что find принимает второй необязательный параметр. Это — список полей, которые мы хотим получить. Например, мы можем получить все имена единорогов следующим запросом:

db.unicorns.find({}, {name: 1});

Поле _id по умолчанию возвращается всегда. Мы можем явным способом исключить его, указав {name:1, _id: 0}.

За исключением поля _id, нельзя смешивать включения и исключения полей. Задумавшись, можно понять, зачем так сделано. Можно или хотеть включить или хотеть наоборот — исключить определённые поля явным образом.

Сортировка

Я уже несколько раз упомянул, что find возвращает курсор, который исполняется отложенно — по мере необходимости. Однако, вы уже без сомнения могли видеть, что find исполняется мгновенно. Такое поведение характерно только для консоли. Можно пронаблюдать за истинным поведением курсоров, взглянув на любой из методов, который мы можем присоединить к find. Первым из них будет sort. Синтаксис sort примерно такой же, как у выбора полей, который мы видели в предыдущем разделе. Мы указываем поля, по которым надо сортировать, используя 1 для сортировки по возрастанию и -1 для сортировки по убыванию. Например:

//сортируем по весу — от тяжёлых к лёгким единорогам
db.unicorns.find().sort({weight: -1})

//по имени единорога, затем по числу убитых вампиров:
db.unicorns.find().sort({name: 1, vampires: -1})

Индекс может помогать сортировке; без подходящего индекса серверу приходится выполнять дополнительную работу. Лимиты памяти и возможность использования диска зависят от операции и версии. Вместо правила «без индекса будет ошибка» проверяйте план запроса через explain и документацию сортировки.

Разбиение на страницы

Разбиение на страницы может быть осуществлено с помощью методов limit и skip. Чтобы получить второго и третьего по весу единорога, можно выполнить:

db.unicorns.find().sort({weight: -1}).limit(2).skip(1)

limit уменьшает число возвращаемых документов, но сам по себе не доказывает дешевизну запроса. Для стабильных страниц добавьте уникальное поле к сортировке, например .sort({weight: -1, _id: 1}). Большой skip требует пропуска всё большего числа результатов; для глубоких страниц рассмотрите диапазонный фильтр по индексированному ключу.

Count

Для точного числа документов по фильтру используйте countDocuments:

db.unicorns.countDocuments({vampires: {$gt: 50}})

Для оценки общего числа документов без фильтра существует estimatedDocumentCount(). Это разные задачи: оценка размера коллекции не заменяет точный подсчёт совпадений. Старые примеры count() не служат универсальным API драйверов. См. countDocuments.

В этой главе

Довольно просто пользоваться find и курсорами. Есть еще несколько дополнительных команд, которые мы либо рассмотрим позже, либо не рассмотрим вообще (так как они применяются лишь в граничных случаях), но теперь, я думаю, вы должны уже освоиться в работе с оболочкой mongosh и пониманием основных принципов MongoDB.

Дальше в книге4. Моделирование данных →
Karl Seguin · перевод @jsmarkus · CC BY-NC 3.0 и авторы