Команда ReQL: filter
Синтаксис команды
selection.filter(predicate_function[, :default => false]) → selection stream.filter(predicate_function[, :default => false]) → stream array.filter(predicate_function[, :default => false]) → array
Описание
Возвращает все элементы в последовательности, для которых заданный предикат истиннен. Результат filter будет таким же, как вход (последовательность, поток или массив). Документы могут быть отфильтрованы различными способами — диапазоны, вложенные значения, булевы условия и результаты анонимных функций.
По умолчанию, filter будет молча пропускать документы с отсутствующими полями: если предикат пытается получить доступ к полю, которого нет (например, предикат {:age => 30} применён к документу без поля age ), этот документ не будет возвращен в результате, и ошибка не будет сгенерирована. Это поведение можно изменить с помощью необязательного аргумента default.
- Если
defaultустановлено вtrue, документы с отсутствующими полями будут возвращены, а не пропущены. - Если
defaultустановлено вr.error(), будет выброшенаReqlRuntimeErrorпри проверке документа с отсутствующим полем. - Если
defaultустановлено вfalse(по умолчанию), документы с отсутствующими полями будут пропущены.
Примечание:
filterне использует вторичные индексы. Для извлечения документов через вторичные индексы рассмотрите команды get_all, between и eq_join.
Основные предикаты
Пример: Получить всех пользователей, которым 30 лет.
r.table('users').filter({:age => 30}).run(conn)
Предикат {'age': 30} выбирает документы в таблице users с полем age, значение которого равно 30. Документы с полем age, установленным на любое другое значение или с отсутствующим полем age пропускаются.
Хотя стиль предиката {'field': value} полезен для точных совпадений, более общий способ написания предиката — использование блока Ruby, который возвращает true или false.
r.table('users').filter{ |user|
user["age"].eq(30)
}.run(conn)
В этом случае функция возвращает true, если поле age равно 30.
Предикаты filter оцениваются на сервере и должны использовать выражения ReQL. Некоторые операторы сравнения Ruby перегружены драйвером RethinkDB и будут преобразованы в ReQL, такие как ==, </> и |/& (обратите внимание на односимвольный формат, а не ||/&&).
Также предикаты должны оценивать поля документов. Они не могут оценивать вторичные индексы.
Пример: Получить всех пользователей, которым больше 18 лет.
r.table("users").filter{ |user|
user["age"] > 18
}.run(conn)
Пример: Получить всех пользователей, которым меньше 18 лет и больше 13 лет.
r.table("users").filter{ |user|
(user["age"] < 18) & (user["age"] > 13)
}.run(conn)
Пример: Получить всех пользователей, которым больше 18 лет или которые дали согласие родителей.
r.table("users").filter{ |user|
(user["age"] >= 18) | (user["hasParentalConsent"])
}.run(conn)
Более сложные предикаты
Пример: Получить всех пользователей, которые подписались между 1 января 2012 года (включительно) и 1 января 2013 года (исключительно).
r.table("users").filter{ |user|
user["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["email"].match("@gmail.com$")
}.run(conn)
Пример: Фильтр на основе наличия значения в массиве.
Предполагая следующую схему для таблицы users:
{
:name => String
:places_visited => [String]
}
Получить всех пользователей, чей поле places_visited содержит France.
r.table("users").filter{|user|
user["places_visited"].contains("France")
}.run(conn)
Пример: Фильтр на основе вложенных полей.
Предполагая следующую схему для таблицы users:
{
:id => String
:name => {
:first => String,
:middle => String,
:last => String
}
}
Получить всех пользователей с именем «Вильям Адама» (имя «Вильям», фамилия «Адама»), с любым отчеством.
r.table("users").filter({
:name => {
:first => "William",
:last => "Adama"
}
}).run(conn)
Если вам нужно точное совпадение для поля, являющегося объектом, вам придется использовать r.literal.
Получить всех пользователей с именем «Вильям Адама» (имя «Вильям», фамилия «Адама»), у которых нет отчества.
r.table("users").filter(r.literal({
:name => {
:first => "William",
:last=> "Adama"
}
})).run(conn)
Вы можете переписать их с помощью блоков.
r.table("users").filter{ |user|
(user["name"]["first"].eq("William")) &
(user["name"]["last"].eq("Adama"))
}.run(conn)
r.table("users").filter{ |user|
user["name"].eq({
:first => "William",
:last => "Adama"
})
}.run(conn)
Обработка отсутствующих полей
По умолчанию, документы с отсутствующими полями, проверенными предикатом filter , пропускаются. В предыдущих примерах пользователи без поля age не возвращаются. Передав необязательный аргумент default к filter, вы можете изменить это поведение.
Пример: Получить всех пользователей младше 18 лет или у которых отсутствует поле age.
r.table("users").filter(:default => true){ |user| user["age"] < 18 }.run(conn)
Пример: Получить всех пользователей старше 18 лет. Выбросить ошибку, если у документа отсутствует поле age.
r.table("users").filter(:default => r.error()){
|user| user["age"] > 18
}.run(conn)
Пример: Получить всех пользователей, которые указали номер телефона (все документы, у которых поле phone_number существует и не равно nil).
r.table('users').filter{ |user|
user.has_fields('phone_number')
}.run(conn)
Пример: Получить всех пользователей с ролью «редактор» или привилегией «админ».
r.table('users').filter{ |user|
user['role'].eq('editor').default(false) |
user['privilege'].eq('admin').default(false)
}.run(conn)
Вместо использования необязательного аргумента default к 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/ruby/filter/