Spec-Zone.ru › RethinkDB ruby

Команда 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, и если у пользователя есть разрешение config, игнорирует любой обработчик записи при выполнении обновления.

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

  • 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{ |post|
    {:views => post["views"]+1}
}.run(conn)

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

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

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

r.table("posts").get(1).update{ |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(:return_changes => true) { |post|
    :views => post["views"]+1
}.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{ |row|
    {:notes => row["notes"].append(new_note)}
}.run(conn)

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

r.table("users").get(10001).update{ |row|
    {:notes => 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{ |row|
    row.has_fields({:contact => {:im => "icq"}})
}.update{ |row|
    {:notes => 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/ruby/update/

Spec-Zone.ru

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