Команда 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)
© RethinkDB contributors
Licensed under the Creative Commons Attribution-ShareAlike 3.0 Unported License.
https://rethinkdb.com/api/ruby/update/