1. Обзор
В этой статье разберемся, как использовать класс Filters для запросов к MongoDB.
Класс Filters представляет собой билдер для удобного написания фильтров запросов. Фильтры — это некоторые условные операции, которые MongoDB использует для ограничения результатов.
2. Типы билдеров
Драйвер MongoDB для Java предоставляет несколько типов билдеров, упрощающих создание BSON-документов и предоставляющих удобный API для выполнения различных CRUD-операций и агрегации.
Доступны следующие билдеры:
Filters — фильтры запросов;
Projections — проекции (какие поля включить, а какие исключить из результата);
Sorts — критерии сортировки;
Updates — операции обновления;
Aggregates — пайплайны агрегации (aggregation pipeline);
Indexes — создание индексов.
Далее рассмотрим использование Filters.
3. Инициализация базы данных
Начнем с создания базы данных и коллекции user, на примере которой и будем рассматривать различные операции фильтрации.
use baeldung; db.createCollection("user");
Заполним коллекцию user несколькими документами:
db.user.insertMany([ { "userId":"123", "userName":"Jack", "age":23, "role":"Admin" }, { "userId":"456", "userName":"Lisa", "age":27, "role":"Admin", "type":"Web" }, { "userId":"789", "userName":"Tim", "age":31, "role":"Analyst" }]);
При выполнении успешной вставки получим следующий ответ:
{ "acknowledged" : true, "insertedIds" : [ ObjectId("6357c4736c9084bcac72eced"), ObjectId("6357c4736c9084bcac72ecee"), ObjectId("6357c4736c9084bcac72ecef") ] }
4. Использование класса Filters
В классе Filters содержатся статические фабричные методы, выполняющие различные операции фильтрации в MongoDB. Каждый из этих методов возвращает экземпляры интерфейса BSON, который можно передать любому методу, ожидающему фильтр запроса.
Класс Filters — это замена QueryBuilder устаревшего API.
Методы в Filters классифицируются по типу выполняемых операций: условные, логические, работа с массивами, проверка существования поля и его типа, побитовые и геопространственные.
Рассмотрим некоторые часто используемые методы Filters.
4.1. Метод eq()
Метод Filters.eq() создает фильтр для получения документов, в которых значение поля равно указанному значению.
Для начала выполним запрос в MongoDB Shell для поиска в коллекции user документов с полем userName равным "Jack":
db.getCollection('user').find({"userName":"Jack"})
Приведенный выше запрос возвращает один документ:
{ "_id" : ObjectId("6357c4736c9084bcac72eced"), "userId" : "123", "userName" : "Jack", "age" : 23.0, "role" : "Admin" }
Далее напишем аналогичный запрос с использованием Filters:
Bson filter = Filters.eq("userName", "Jack"); FindIterable<Document> documents = collection.find(filter); MongoCursor<Document> cursor = documents.iterator(); while (cursor.hasNext()) { System.out.println(cursor.next()); }
Можно заметить, что метод Filters.eq() возвращает тип BSON, который затем передается в метод find() в качестве фильтра.
Также есть метод Filters.ne(), который прямо противоположен методу Filters.eq() — выбираются все документы со значением поля не равным указанному значению:
Bson filter = Filters.ne("userName", "Jack"); FindIterable<Document> documents = collection.find(filter); MongoCursor<Document> cursor = documents.iterator(); while (cursor.hasNext()) { System.out.println(cursor.next()); }
4.2. Метод gt()
Метод Filters.gt() создает фильтр для получения документов, в которых значение поля больше заданного значения.
Рассмотрим следующий пример:
Bson filter = Filters.gt("age", 25); FindIterable<Document> documents = collection.find(filter); MongoCursor<Document> cursor = documents.iterator(); while (cursor.hasNext()) { System.out.println(cursor.next()); }
В приведенном примере извлекаются документы, в которых возраст (age) превышает 25 лет.
Аналогично методу Filters.gt(), есть метод Filters.lt(), который соответствует документам, имеющим значение поля меньше указанного:
Bson filter = Filters.lt("age", 25); FindIterable<Document> documents = collection.find(filter); MongoCursor<Document> cursor = documents.iterator(); while (cursor.hasNext()) { System.out.println(cursor.next()); }
Существуют еще методы Filters.gte() и Filters.lte(), которые соответствуют значениям "больше или равно" и "меньше или равно" соответственно.
4.3. Метод in()
Метод Filters.in() создаёт фильтр для получения документов, в которых значение поля равно одному из значений в списке.
Давайте посмотрим на пример:
Bson filter = Filters.in("userName", "Jack", "Lisa"); FindIterable<Document> documents = collection.find(filter); MongoCursor<Document> cursor = documents.iterator(); while (cursor.hasNext()) { System.out.println(cursor.next()); }
Здесь мы получаем документы, в которых userName равно "Jack" или "Lisa".
Подобно методу Filters.in() есть метод Filters.nin(), который выбирает документы со значением поля не равным ни одному из значений списка:
Bson filter = Filters.nin("userName", "Jack", "Lisa"); FindIterable<Document> documents = collection.find(filter); MongoCursor<Document> cursor = documents.iterator(); while (cursor.hasNext()) { System.out.println(cursor.next()); }
4.4. Метод and()
Метод Filters.and() создает фильтр, выполняющий логическую операцию "И" для переданного списка фильтров.
Давайте найдем пользователей с возрастом (age) больше 25 лет и ролью (role) "Admin":
Bson filter = Filters.and(Filters.gt("age", 25), Filters.eq("role", "Admin")); FindIterable<Document> documents = collection.find(filter); MongoCursor<Document> cursor = documents.iterator(); while (cursor.hasNext()) { System.out.println(cursor.next()); }
4.5. Метод or()
Как и следовало ожидать, метод Filters.or() выполняет логическую операцию "ИЛИ".
Давайте напишем пример, который возвращает пользователей с возрастом (age) больше 30 или ролью (role) "Admin":
Bson filter = Filters.or(Filters.gt("age", 30), Filters.eq("role", "Admin")); FindIterable<Document> documents = collection.find(filter); MongoCursor<Document> cursor = documents.iterator(); while (cursor.hasNext()) { System.out.println(cursor.next()); }
4.6. Метод exists()
Метод Filters.exists() ищет документы, в которых присутствует указанное поле.
Bson filter = Filters.exists("type"); FindIterable<Document> documents = collection.find(filter); MongoCursor<Document> cursor = documents.iterator(); while (cursor.hasNext()) { System.out.println(cursor.next()); }
Приведенный выше код возвращает документы коллекции user, в которых есть поле type.
4.7. Метод regex()
Наконец, метод Filters.regex() проверяет поле документа на соответствие заданному регулярному выражению.
Bson filter = Filters.regex("userName", "a"); FindIterable<Document> documents = collection.find(filter); MongoCursor<Document> cursor = documents.iterator(); while (cursor.hasNext()) { System.out.println(cursor.next()); }
Здесь мы извлекаем все документы, в которых userName соответствует регулярному выражению "a".
Мы рассмотрели некоторые из наиболее часто используемых операторов фильтрации. В качестве фильтра в методе find() можно использовать любую комбинацию операторов фильтрации.
Более того, фильтры могут использоваться и в других местах, например, в пайплайне агрегации, в методах deleteOne() и updateOne() и др.
5. Заключение
В этой статье мы обсудили, как использовать билдер Filters для выполнения операций фильтрации коллекций MongoDB.
Полный код всех примеров доступен на GitHub.
На пути от монолита к микросервисам нас ожидают множество мелких неприятностей, которые могут стать серьезной проблемой по мере развития проекта. Скоро пройдет открытый урок, на котором мы рассмотрим, как легко и изящно можно их преодолеть с помощью инструментов от Spring Cloud. Регистрируйтесь по ссылке.
