Фильтрация полей в MongoDB: быстрая выборка данных

Фильтрующие запросы — крайне полезная возможность MongoDB, часто недооцениваемая. Рассмотрим её работу.

В базе данных MongoDB документы могут иметь вложенные структуры, потенциально многоуровневые, и быть достаточно большими. При чтении весь документ передаётся с сервера на клиент. Часто нужны лишь несколько полей. В этом случае требуется получить подмножество полей основного документа.

Существуют два подхода:

  1. Получить полный документ с сервера MongoDB и выполнить фильтрацию полей на стороне клиента. Это неэффективно: расходуются лишние ресурсы и увеличивается задержка.
  2. Выполнить фильтрацию полей на сервере перед отправкой документа клиенту. Этот вариант предпочтительнее: клиент получает только необходимые данные, экономя трафик и уменьшая задержку.

Мы рассмотрим фильтрацию полей на стороне сервера.

Примеры фильтрации

Используем метод find (метод findOne также поддерживает фильтрацию). find принимает два аргумента: объект запроса и объект фильтрации полей. Объект фильтрации содержит пары «ключ-значение», где ключ — имя поля, а значение — 1 (включить поле) или 0 (исключить поле). Поле _id включается по умолчанию, если явно не указано _id: 0.

Включение полей name и age

Включаем поля name и age. Поле _id будет включено по умолчанию. Результат — документы с тремя полями.

Включение вложенного поля

Включаем вложенное поле company.location, age и _id.

Исключение поля _id

Исключаем поле _id и включаем name и age. Исключение _id обычно не требуется, так как каждый документ должен иметь уникальный идентификатор.

Исключение нескольких полей

Для исключения нескольких полей из документа, достаточно указать их со значением 0. Остальные поля будут включены.

Практическое применение

Рассмотрим коллекцию persons. Запрос db.persons.find() вернёт все документы со всеми полями. Для фильтрации полей добавляем второй аргумент к find:

db.persons.find({}, { name: 1, age: 1, eyeColor: 1 })

Этот запрос вернёт документы с полями name, age, eyeColor, и _id (по умолчанию).

Фильтрация вложенных документов

Добавим поле company:

db.persons.find({}, { name: 1, age: 1, "company.location": 1 })

Вернёт только поле location из вложенного документа company.

Исключение поля _id и других полей

db.persons.find({}, { _id: 0, name: 1, age: 1 })

Исключение полей name и age

db.persons.find({}, { name: 0, age: 0 })

Фильтрация с findOne

Фильтрующие запросы работают и с методом findOne:

db.persons.findOne({}, { name: 1, age: 1 })

Фильтрующие запросы (проекции) позволяют преобразовывать большие документы в меньшие, отправляя клиенту только необходимые данные. Рекомендуется использовать этот метод для повышения эффективности запросов.

Что будем искать? Например,программа