Spec-Zone.ru › RethinkDB python

Команда ReQL: update

Синтаксис команды

table.update(object | function[, durability="hard", return_changes=False, non_atomic=False, ignore_write_hook=False]) → object
selection.update(object | function[, durability="hard", return_changes=False, non_atomic=False, ignore_write_hook=False]) → object
singleSelection.update(object | function[, durability="hard", return_changes=False, non_atomic=False, ignore_write_hook=False]) → object

Описание

Обновляет JSON-документы в таблице. Принимает JSON-документ, выражение ReQL или комбинацию обоих.

Необязательные аргументы:

  • durability: возможные значения — hard и soft. Этот параметр переопределит настройку долговечности таблицы или запроса (установленную в run). В режиме мягкой долговечности RethinkDB подтвердит запись сразу после её получения, но перед тем как запись будет сохранена на диск.
  • return_changes:
    • True: возвращает массив changes, состоящий из объектов old_val/new_val, описывающих внесённые изменения, включающий только документы, которые были фактически обновлены.
    • False: не возвращает массив changes (по умолчанию).
    • "always": ведет себя как True, но включает все документы, которые команда пыталась обновить, независимо от того, было ли обновление успешным. (Это было поведение True до версии 2.0.)
  • non_atomic: если установлено в значение True, выполняет обновление и распределяет результат репликам неатомным способом. Этот флаг необходим для выполнения недетерминированных обновлений, таких как те, которые требуют чтения данных из другой таблицы.
  • ignore_write_hook: Если True, и если у пользователя есть разрешение на конфигурацию, игнорирует любой write hook при выполнении обновления.

Обновление возвращает объект, содержащий следующие атрибуты:

  • replaced: количество документов, которые были обновлены.
  • unchanged: количество документов, которые были бы изменены, за исключением случаев, когда новое значение было таким же, как и старое.
  • skipped: количество документов, которые были пропущены, потому что документ не существовал.
  • errors: количество ошибок, возникших при выполнении обновления.
  • first_error: Если возникли ошибки, содержит текст первой ошибки.
  • deleted и inserted: 0 для операции обновления.
  • changes: если return_changes установлено в значение True, это будет массив объектов, по одному для каждого объекта, затронутого операцией update. Каждый объект будет иметь два ключа: {"new_val": <new value>, "old_val": <old value>}.

Операции записи RethinkDB будут выбрасывать исключения только в том случае, если ошибки возникнут до выполнения любых записей. Другие ошибки будут перечислены в first_error, и errors будет установлено в ненулевое значение. Для правильной обработки ошибок с этим термином код должен обрабатывать как исключения, так и проверять возвращаемое значение errors!

Пример: Обновить статус поста с id от 1 до published.

r.table("posts").get(1).update({"status": "published"}).run(conn)

Пример: Обновить статус всех постов до published.

r.table("posts").update({"status": "published"}).run(conn)

Пример: Обновить статус всех постов, написанных Вильямом.

r.table("posts").filter({"author": "William"}).update({"status": "published"}).run(conn)

Обратите внимание, что операции filter, get_all и аналогичные операции не выполняются атомарно с update. См. Гарантии согласованности для получения дополнительной информации. Также см. пример условных обновлений ниже для решения, использующего branch в update условии.

Пример: Увеличить поле view поста с id от 1 . Этот запрос выбросит ошибку, если поле views не существует.

r.table("posts").get(1).update({
    "views": r.row["views"]+1
}).run(conn)

Пример: Увеличить поле view поста с id от 1 . Если поле views не существует, оно будет установлено в 0.

r.table("posts").get(1).update({
    "views": (r.row["views"]+1).default(0)
}).run(conn)

Пример: Выполнить условное обновление.
Если пост просмотрен более чем 100 раз, установить type поста на hot, в противном случае установить его на normal.

r.table("posts").get(1).update(lambda post:
    r.branch(
        post["views"] > 100,
        {"type": "hot"},
        {"type": "normal"}
    )
).run(conn)

Пример: Обновить поле num_comments результатом подзапроса. Поскольку это обновление не является атомным, вы должны передать флаг non_atomic.

r.table("posts").get(1).update({
    "num_comments": r.table("comments").filter({"id_post": 1}).count()
}, non_atomic=True).run(conn)

Если вы забудете указать флаг non_atomic , вы получите ReqlRuntimeError:

ReqlRuntimeError: Could not prove function deterministic.  Maybe you want to use the non_atomic flag? 

Пример: Обновить поле num_comments случайным значением между 0 и 100. Это обновление не может быть доказано детерминированным из-за r.js (и на самом деле не является), поэтому вы должны передать флаг non_atomic.

r.table("posts").get(1).update({
    "num_comments": r.js("Math.floor(Math.random()*100)")
}, non_atomic=True).run(conn)

Пример: Обновить статус поста с id от 1 с помощью мягкой долговечности.

r.table("posts").get(1).update({status: "published"}, durability="soft").run(conn)

Пример: Увеличить поле views и вернуть значения документа до и после операции обновления.

r.table("posts").get(1).update({
    "views": r.row["views"]+1
}, return_changes=True).run(conn)

Результат теперь будет включать поле changes:

{
    "deleted": 0,
    "errors": 0,
    "inserted": 0,
    "changes": [
        {
            "new_val": {
                "id": 1,
                "author": "Julius_Caesar",
                "title": "Commentarii de Bello Gallico",
                "content": "Aleas jacta est",
                "views": 207
            },
            "old_val": {
                "id": 1,
                "author": "Julius_Caesar",
                "title": "Commentarii de Bello Gallico",
                "content": "Aleas jacta est",
                "views": 206
            }
        }
    ],
    "replaced": 1,
    "skipped": 0,
    "unchanged": 0
}

Обновление вложенных полей

Команда update поддерживает синтаксис вложенных полей RethinkDB для обновления поддокументов. Рассмотрим таблицу пользователей с контактной информацией в таком формате:

{
    "id": 10001,
    "name": "Bob Smith",
    "contact": {
        "phone": {
            "work": "408-555-1212",
            "home": "408-555-1213",
            "cell": "408-555-1214"
        },
        "email": {
            "work": "bob@smith.com",
            "home": "bobsmith@example.com",
            "other": "bobbys@moosecall.net"
        },
        "im": {
            "skype": "Bob Smith",
            "aim": "bobmoose",
            "icq": "nobodyremembersicqnumbers"
        }
    },
    "notes": [
        {
            "date": r.time(2014,1,1,'Z'),
            "from": "John Doe",
            "subject": "My name is even more boring than Bob's"
        },
        {
            "date": r.time(2014,2,2,'Z'),
            "from": "Bob Smith Sr",
            "subject": "Happy Second of February"
        }
    ]
}

Пример: Обновить номер мобильного телефона Боба Смита.

r.table("users").get(10001).update(
    {"contact": {"phone": {"cell": "408-555-4242"}}}
).run(conn)

Пример: Добавить другую заметку в запись Боба Смита.

new_note = {
    "date": r.now(),
    "from": "Inigo Montoya",
    "subject": "You killed my father"
}
r.table("users").get(10001).update(
    {"notes": r.row["notes"].append(new_note)}
).run(conn)

Это приведет к ошибке, если поле notes не существует в документе. Для выполнения этого как «upsert» (обновление или вставка), используйте команду default для инициализации поля как пустого списка.

r.table("users").get(10001).update(
    {"notes": r.row["notes"].default([]).append(new_note)}
).run(conn)

Пример: Отправить заметку каждому пользователю с номером ICQ.

icq_note = {
    "date": r.now(),
    "from": "Admin",
    "subject": "Welcome to the future"
}
r.table("users").filter(
    r.row.has_fields({"contact": {"im": "icq"}})
).update(
    {"notes": r.row["notes"].append(icq_note)}
).run(conn)

Пример: Заменить все записи IM Боба. Обычно update объединит вложенные документы; чтобы заменить весь документ "im", используйте команду literal.

r.table('users').get(10001).update(
    {"contact": {"im": r.literal({"aim": "themoosemeister"})}}
).run(conn)

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

  • insert
  • replace
  • delete

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

Spec-Zone.ru

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