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