Spec-Zone.ru › RethinkDB java

Команда 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);

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

  • insert
  • replace
  • delete

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

Spec-Zone.ru

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