Команда ReQL: filter
Синтаксис команды
selection.filter(predicate_function) → selection stream.filter(predicate_function) → stream array.filter(predicate_function) → array
Описание
Возвращает все элементы в последовательности, для которых заданный предикат является истинным. Результатом filter будет то же, что и входные данные (последовательность, поток или массив). Документы могут быть отфильтрованы различными способами — диапазоны, вложенные значения, булевы условия и результаты анонимных функций.
По умолчанию, filter будет игнорировать документы с отсутствующими полями: если предикат пытается получить доступ к полю, которого нет (например, предикат {age: 30} применяется к документу без поля age), этот документ не будет включён в результирующий набор, и ошибка не будет сгенерирована. Это поведение можно изменить с помощью default optArg.
- Если
defaultустановлено вtrue, документы с отсутствующими полями будут возвращены, а не пропущены. - Если
defaultустановлено вr.error(), будет выброшена ошибкаReqlRuntimeError, когда проверяется документ с отсутствующим полем. - Если
defaultустановлено вfalse(по умолчанию), документы с отсутствующими полями будут пропущены.
Примечание:
filterне использует вторичные индексы. Для получения документов через вторичные индексы рассмотрите использование getAll, between и eqJoin.
Базовые предикаты
Пример: Получить всех пользователей, которым 30 лет.
r.table("users").filter(r.hashMap(age, 30)).run(conn);
Предикат r.hashMap(age, 30) выбирает документы в таблице users с полем age, значение которого равно 30. Документы с полем age, установленным на любое другое значение или без поля age будут пропущены.
Хотя стили предикатов r.hashMap(field, value) полезны для точных совпадений, более универсальный способ написания предиката — использовать анонимную функцию, которая возвращает true или false.
r.table("users").filter(row -> row.g("age").eq(30)).run(conn);
В этом случае функция возвращает true, если поле age равно 30.
Предикаты, используемые в filter , оцениваются на сервере и должны использовать выражения ReQL. Нельзя использовать стандартные операторы сравнения Java, такие как ==, </> и ||/&&.
Пример: Получить всех пользователей, которым больше 18 лет.
r.table("users").filter(row -> row.g("age").gt(18)).run(conn);
Пример: Получить всех пользователей, которым меньше 18 лет и больше 13 лет.
r.table("users").filter(
row -> row.g("age").lt(18).and(row.g("age").gt(13))
).run(conn);
Пример: Получить всех пользователей, которым больше 18 лет или у которых есть родительское разрешение.
r.table("users").filter(
row -> row.g("age").ge(18).or(row.g("hasParentalConsent"))
).run(conn);
Более сложные предикаты
Пример: Получить всех пользователей, которые подписались между 1 января 2012 года (включительно) и 1 января 2013 года (исключительно).
r.table("users").filter(
user -> user.g("subscription_date").during(
r.time(2012, 1, 1, "Z"), r.time(2013, 1, 1, "Z"))
).run(conn);
Пример: Получить всех пользователей, у которых есть аккаунт gmail (поле email заканчивается на @gmail.com).
r.table("users").filter(
user -> user.g("email").match("@gmail.com$")
).run(conn);
Пример: Фильтрация на основе наличия значения в массиве.
Учитывая эту схему для таблицы users:
{
"name": String
"placesVisited": [String]
}
Получить всех пользователей, чьё поле placesVisited содержит France.
r.table("users").filter(
user -> user.g("placesVisited").contains("France")
).run(conn);
Пример: Фильтрация на основе вложенных полей.
Учитывая эту схему для таблицы users:
{
"id": String
"name": {
"first": String,
"middle": String,
"last": String
}
}
Получить всех пользователей с именем «Вильям Адама» (имя «Вильям», фамилия «Адама»), с любым отчеством.
r.table("users").filter(
r.hashMap("name", r.hashMap("first", "William").with("last", "Adama"))
).run(conn);
Если вам нужно точное совпадение для поля, являющегося объектом, вам нужно использовать r.literal.
Получить всех пользователей с именем «Вильям Адама» (имя «Вильям», фамилия «Адама»), у которых нет отчества.
r.table("users").filter(r.literal(
r.hashMap("name", r.hashMap("first", "William").with("last", "Adama"))
)).run(conn);
Вы можете переписать это с помощью анонимных функций.
r.table("users").filter(
user -> user.g("name").g("first").eq("William")
.and(user.g("name").g("last").eq("Adama"))
).run(conn);
r.table("users").filter(
user -> user.g("name")
.eq(r.hashMap("first", "William").with("last", "Adama"))
).run(conn);
Обработка отсутствующих полей
По умолчанию, документы с отсутствующими полями, проверяемыми предикатом filter , пропускаются. В предыдущих примерах пользователи без поля age не возвращаются. Передавая необязательный аргумент default в filter, вы можете изменить это поведение.
Пример: Получить всех пользователей младше 18 лет или у которых отсутствует поле age.
r.table("users").filter(row -> row.g("age").lt(18)).optArg("default", true).run(conn);
Пример: Получить всех пользователей старше 18 лет. Выбросить ошибку, если у документа отсутствует поле age.
r.table("users").filter(row -> row.g("age").gt(18))
.optArg("default", r.error()).run(conn);
Пример: Получить всех пользователей, которые указали свой номер телефона (все документы, у которых поле phoneNumber существует и не равно null).
r.table("users").filter(user -> user.hasFields("phone_number")).run(conn);
Пример: Получить всех пользователей с ролью «editor» или привилегием «admin».
r.table("users").filter(
user -> user.g("role").eq("editor").default_(false)
.or(user.g("privilege").eq("admin").default_(false))
).run(conn);
Вместо использования default optArg с filter, мы должны использовать значения по умолчанию для полей в or задании. Почему? Если поле слева в or задании отсутствует в документе (в данном случае, если у пользователя отсутствует поле role ), предикат сгенерирует ошибку, и вернёт false (или значение, указанное в аргументе default ), не оценивая правую часть or. Используя .default_(false) для полей, каждая часть or будет оцениваться как значение поля или false, если поле отсутствует.
© RethinkDB contributors
Licensed under the Creative Commons Attribution-ShareAlike 3.0 Unported License.
https://rethinkdb.com/api/java/filter/