Spec-Zone.ru › RethinkDB python

Команда 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} удобен для точных совпадений, более общий способ написания предиката — использование команды row с оператором сравнения, таким как eq (==) или gt (>), или использование лямбда-функции, которая возвращает True или False.

r.table('users').filter(r.row["age"] == 30).run(conn)

В этом случае предикат r.row["age"] == 30 возвращает True, если поле age равно 30. Вы можете записать этот предикат как лямбда-функцию:

r.table('users').filter(lambda user:
    user["age"] == 30
).run(conn)

Предикаты для filter оцениваются на сервере и должны использовать выражения ReQL. Некоторые операторы сравнения Python перегружены драйвером RethinkDB и будут переведены в ReQL, такие как ==, </> и |/& (обратите внимание на односимвольный формат, а не ||/&&).

Кроме того, предикаты должны оценивать поля документов. Они не могут оценивать вторичные индексы.

Пример: Получить всех пользователей, которым больше 18 лет.

r.table("users").filter(r.row["age"] > 18).run(conn)

Пример: Получить всех пользователей, которым меньше 18 лет и больше 13 лет.

r.table("users").filter((r.row["age"] < 18) & (r.row["age"] > 13)).run(conn)

Пример: Получить всех пользователей, которым больше 18 лет или у которых есть разрешение родителей.

r.table("users").filter(
    (r.row["age"] >= 18) | (r.row["hasParentalConsent"])).run(conn)

Более сложные предикаты

Пример: Получить всех пользователей, которые подписались между 1 января 2012 года (включительно) и 1 января 2013 года (исключительно).

r.table("users").filter(
    lambda 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(
    lambda user: user["email"].match("@gmail.com$")
).run(conn)

Пример: Фильтрация на основе наличия значения в массиве.

Учитывая эту схему для таблицы users:

{
    "name": <type 'str'>
    "places_visited": [<type 'str'>]
}

Получить всех пользователей, у которых поле places_visited содержит France.

r.table("users").filter(lambda user:
    user["places_visited"].contains("France")
).run(conn)

Пример: Фильтрация на основе вложенных полей.

Учитывая эту схему для таблицы users:

{
    "id": <type 'str'>
    "name": {
        "first": <type 'str'>,
        "middle": <type 'str'>,
        "last": <type 'str'>
    }
}

Получить всех пользователей с именем «Уильям Адама» (имя «Уильям», фамилия «Адама»), с любым отчеством.

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(
    lambda user:
    (user["name"]["first"] == "William")
        & (user["name"]["last"] == "Adama")
).run(conn)
r.table("users").filter(lambda user:
    user["name"] == {
        "first": "William",
        "last": "Adama"
    }
).run(conn)

Обработка отсутствующих полей

По умолчанию, документы, у которых отсутствуют поля, проверенные предикатом filter, пропускаются. В предыдущих примерах, пользователи без поля age не возвращаются. Передав необязательный аргумент default команде filter, вы можете изменить это поведение.

Пример: Получить всех пользователей младше 18 лет или у которых отсутствует поле age.

r.table("users").filter(r.row["age"] < 18, default=True).run(conn)

Пример: Получить всех пользователей старше 18 лет. Выбросить ошибку, если у документа отсутствует поле age.

r.table("users").filter(r.row["age"] > 18, default=r.error()).run(conn)

Пример: Получить всех пользователей, которые указали номер телефона (все документы, у которых поле phone_number существует и не равно None).

r.table('users').filter(
    lambda user: user.has_fields('phone_number')
).run(conn)

Пример: Получить всех пользователей с ролью «редактор» или привилегиями «админ».

r.table('users').filter(
    lambda user: (user['role'] == 'editor').default(False) |
        (user['privilege'] == 'admin').default(False)
).run(conn)

Вместо использования необязательного аргумента default к команде filter, мы должны использовать значения по умолчанию для полей в инструкции or. Почему? Если поле слева от оператора сравнения or отсутствует в документе — в этом случае, если у пользователя нет поля role, — предикат сгенерирует ошибку и вернёт False (или значение, заданное аргументом default) без оценки правой части or. Используя .default(False), каждая сторона оператора сравнения or будет оцениваться либо как значение поля, либо как False, если поле отсутствует.

Связанные команды

  • get
  • get_all
  • between

© RethinkDB contributors
Licensed under the Creative Commons Attribution-ShareAlike 3.0 Unported License.
https://rethinkdb.com/api/python/filter/

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API