Команда ReQL: update
Синтаксис команды
table.update(object | function) → object selection.update(object | function) → object singleSelection.update(object | function) → object
Описание
Обновление JSON-документов в таблице. Принимает JSON-документ, выражение ReQL или комбинацию обоих.
Вы можете передать следующие параметры с помощью optArg:
-
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(r.hashMap("status", "published")).run(conn);
Пример: Обновить статус всех постов до published.
r.table("posts").update(r.hashMap("status", "published")).run(conn);
Пример: Обновить статус всех постов, написанных Уильямом.
r.table("posts").filter(
r.hashMap("author", "William")).update(r.hashMap("status", "published")
).run(conn);
Обратите внимание, что операции
filter,getAllи подобные операции не выполняются атомарно сupdate. Подробнее см. Гарантии согласованности. Также см. пример условных обновлений ниже для решения, использующегоbranchвupdate-клаузе.
Пример: Увеличить поле view поста с id от 1. Этот запрос выдаст ошибку, если поле views не существует.
r.table("posts").get(1).update(
post -> r.hashMap("views", post.g("views").add(1))
).run(conn);
Пример: Увеличить поле view поста с id от 1. Если поле views не существует, оно будет установлено в 0.
r.table("posts").get(1).update(
post -> r.hashMap("views", post.g("views").add(1).default_(0))
).run(conn);
Пример: Выполнить условное обновление.
Если у поста более 100 просмотров, установить type поста в hot, иначе установить его в normal.
r.table("posts").get(1).update(
post -> r.branch(post.g("views").gt(100),
r.hashMap("type", "hot"),
r.hashMap("type", "normal")
)
).run(conn);
Пример: Обновить поле numComments результатом подзапроса. Поскольку это обновление не атомарно, вы должны передать флаг non_atomic.
r.table("posts").get(1).update(
r.hashMap("numComments", r.table("comments")
.filter(r.hashMap("id_post", 1)).count())
).optArg("non_atomic", true).run(conn);
Если вы забудете указать флаг non_atomic , вы получите ReqlRuntimeError:
ReqlRuntimeError: Could not prove function deterministic. Maybe you want to use the non_atomic flag?
Пример: Обновить поле numComments случайным значением от 0 до 100. Это обновление нельзя доказать детерминированным из-за r.js (и фактически оно таковым не является), поэтому вы должны передать флаг nonAtomic.
r.table("posts").get(1).update(
r.hashMap("numComments", r.js("Math.floor(Math.random()*100)"))
).optArg("non_atomic", true).run(conn);
Пример: Обновить статус поста с id от 1 с мягкой долговечностью.
r.table("posts").get(1).update(
r.hashMap(status, "published")
).optArg("durability", "soft").run(conn);
Пример: Увеличить поле views и вернуть значения документа до и после операции обновления.
r.table("posts").get(1).update(
post -> r.hashMap("views", post.g("views").add(1))
).optArg("return_changes", true).run(conn);
Результат теперь будет включать поле changes:
{
"deleted": 1,
"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": 0,
"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(
r.hashMap("contact",
r.hashMap("phone",
r.hashMap("cell", "408-555-4242")))
).run(conn);
Пример: Добавить ещё одну заметку в запись Боба Смита.
import com.rethinkdb.model.MapObject;
MapObject newNote = r.hashMap("date", r.now())
.with("from", "Admin")
.with("subject", "You killed my father");
r.table("users").get(10001).update(
row -> r.hashMap("notes", row.g("notes").append(newNote))
).run(conn);
Это приведёт к ошибке, если поле notes не существует в документе. Для выполнения этого как «upsert» (обновление или вставка), используйте команду default_, чтобы убедиться, что поле инициализировано как пустой список.
r.table("users").get(10001).update(
row -> r.hashMap(notes, row.g("notes").default_(r.array()).append(newNote))
).run(conn);
Пример: Отправить заметку каждому пользователю с номером ICQ.
import com.rethinkdb.model.MapObject;
MapObject icqNote = r.hashMap("date", r.now())
.with("from", "Admin")
.with("subject", "Welcome to the future");
r.table("users").filter(
row -> row.hasFields(r.hashMap("contact", r.hashMap("im", "icq")))
).update(r.hashMap("notes", row.g("notes").append(icqNote))).run(conn);
Пример: Заменить все записи IM Боба. Обычно update будет объединять вложенные документы; чтобы заменить весь документ "im", используйте команду literal.
r.table("users").get(10001).update(
r.hashMap("contact",
r.hashMap("im",
r.literal(r.hashMap("aim", "themoosemeister"))))
).run(conn);
© RethinkDB contributors
Licensed under the Creative Commons Attribution-ShareAlike 3.0 Unported License.
https://rethinkdb.com/api/java/update/