REPLACE¶
Каждая операция REPLACE ограничена одной коллекцией, и имя коллекции не должно быть динамическим. В одном запросе AQL допускается только один оператор REPLACE для коллекции, и за ним не могут следовать операции чтения или записи, обращающиеся к той же коллекции, операции обхода или функции AQL, которые могут читать документы.
Нельзя заменить системные атрибуты _id, _key и _rev, но можно заменить атрибуты _from и _to.
Замена документа изменяет номер ревизии документа (атрибут _rev) на генерируемое сервером значение.
Синтаксис¶
Для операции замены существует два синтаксиса:
REPLACE document IN collection
REPLACE keyExpression WITH document IN collection Оба варианта могут опционально заканчиваться предложением OPTIONS { ... }.
collection должно содержать имя коллекции, в которой должен быть заменен документ.
document должен быть объектом и содержать атрибуты и значения для установки. Все существующие атрибуты в хранимом документе удаляются из него и устанавливаются только предоставленные атрибуты (за исключением неизменяемых атрибутов _id и _key и управляемого системой атрибута _rev). Это отличает операцию REPLACE от операции UPDATE, которая влияет только на атрибуты, указанные в операции, и не изменяет другие атрибуты хранимого документа.
REPLACE <document> IN <collection>¶
При использовании первого синтаксиса объект document должен иметь атрибут _key с ключом документа. Существующий документ с этим ключом заменяется атрибутами, предоставленными объектом document (за исключением системных атрибутов _id, _key и _rev).
Следующий запрос заменяет документ, идентифицированный ключом my_key в коллекции users, устанавливая только атрибуты name и status. Ключ передается через атрибут _key наряду с другими атрибутами:
1 | |
Следующий запрос недействителен, поскольку объект не содержит атрибута _key, и поэтому невозможно определить заменяемый документ:
1 | |
Вы можете объединить операцию REPLACE с циклом FOR для определения необходимых ключевых атрибутов, как показано ниже:
1 2 | |
Обратите внимание, что операции REPLACE и FOR независимы друг от друга, и u не определяет автоматически документ для оператора REPLACE. Таким образом, следующий запрос является некорректным:
1 2 | |
REPLACE <keyExpression> WITH <document> IN <collection>¶
При использовании второго синтаксиса документ для замены определяется keyExpression. Это может быть либо строка с ключом документа, либо объект, содержащий атрибут _key с ключом документа, либо выражение, которое оценивается как одно из этих двух. Существующий документ с этим ключом заменяется атрибутами, предоставленными объектом document (за исключением системных атрибутов _id, _key и _rev).
Следующий запрос заменяет документ, идентифицированный ключом my_key в коллекции users, устанавливая только атрибуты name и status. Ключ передается в виде строки в keyExpression. Атрибуты для установки передаются отдельно в виде объекта document:
1 | |
Объект document может содержать атрибут _key, но он игнорируется.
Вы не можете определить документ для замены с помощью атрибута _id или передать идентификатор документа в виде строки (например, "users/john"). Однако вы можете использовать PARSE_IDENTIFIER(<id>).key в качестве keyExpression, чтобы получить ключ документа в виде строки:
1 2 | |
Сравнение синтаксисов¶
Оба синтаксиса операции REPLACE позволяют вам определить документ для изменения и атрибуты для установки. Документ для обновления эффективно идентифицируется ключом документа в сочетании с указанной коллекцией.
Операция REPLACE поддерживает различные способы указания ключа документа. Вы можете выбрать наиболее удобный для вас вариант синтаксиса.
Следующие запросы эквивалентны:
1 2 | |
1 2 | |
1 2 | |
1 2 | |
Выражения динамических ключей¶
Операция REPLACE может заменять произвольные документы, используя любой из двух синтаксисов:
1 2 | |
1 2 | |
Нацелить на другую коллекцию¶
Документы, которые изменяет операция REPLACE, могут находиться в другой коллекции, чем те, которые были созданы предшествующей операцией FOR:
1 2 3 | |
Обратите внимание, как документы считываются из коллекции users, но заменяются в другой коллекции backup. Для того чтобы это сработало, обе коллекции должны использовать совпадающие ключи документов.
Хотя переменная u содержит целый документ, она используется только для определения целевого документа. Атрибут _key объекта извлекается, и целевой документ определяется только значением строки ключа документа и указанной коллекцией операции REPLACE (backup). Ссылка на исходную коллекцию (users) отсутствует.
Параметры запроса¶
Вы можете опционально задать параметры запроса для операции REPLACE:
1 | |
ignoreErrors¶
Вы можете использовать ignoreErrors для подавления ошибок запроса, которые могут возникнуть при попытке заменить несуществующие документы или при нарушении ограничений уникального ключа:
1 2 3 4 | |
Вы не можете изменять системные атрибуты _id, _key и _rev, но попытки изменить их игнорируются и не считаются ошибками.
waitForSync¶
Для обеспечения долговечности данных при возврате запроса замены существует опция запроса waitForSync:
1 2 3 4 | |
ignoreRevs¶
Чтобы случайно не перезаписать документы, которые были изменены с момента последнего извлечения, вы можете использовать опцию ignoreRevs, чтобы либо позволить ArangoDB сравнивать значение _rev и добиваться успеха, только если они совпадают, либо позволить ArangoDB игнорировать их (по умолчанию):
1 2 3 4 | |
exclusive¶
Движок RocksDB не требует блокировок на уровне коллекции. Различные операции записи в одну и ту же коллекцию не блокируют друг друга, если нет конфликтов запись-запись на одних и тех же документах. С точки зрения разработки приложений может быть желательным иметь исключительный доступ на запись в коллекции, чтобы упростить разработку. Обратите внимание, что записи не блокируют чтения в RocksDB. Исключительный доступ также может ускорить запросы на модификацию, поскольку мы избегаем проверки конфликтов.
Используйте опцию exclusive для достижения этого эффекта на основе каждого запроса:
1 2 3 4 | |
refillIndexCaches¶
Нужно ли обновлять существующие записи в кэше границ в памяти, если документы границ заменяются.
1 2 | |
Возвращение измененных документов¶
При желании можно вернуть документы, измененные запросом. В этом случае за операцией REPLACE должна следовать операция RETURN. Допускаются также промежуточные операции LET. Эти операции могут ссылаться на псевдопеременные OLD и NEW. Псевдопеременная OLD ссылается на ревизии документа до замены, а NEW - на ревизии документа после замены.
И OLD, и NEW содержат все атрибуты документа, даже те, которые не указаны в выражении replace.
1 2 3 4 | |
Ниже приведен пример с использованием переменной previous для возврата исходных документов до их модификации. Для каждого замененного документа возвращается ключ документа:
1 2 3 4 | |
Следующий запрос использует псевдо-значение NEW, чтобы вернуть замененные документы без некоторых их системных атрибутов:
1 2 3 4 | |
Транзакционность¶
На одном сервере операции замены выполняются транзакционно по принципу "все или ничего".
Если используется движок RocksDB и включены промежуточные фиксации, запрос может выполнять промежуточные фиксации транзакций в случае, если запущенная транзакция (AQL-запрос) достигает заданных пороговых значений размера. В этом случае операции запроса, выполненные до этого момента, фиксируются и не откатываются в случае последующего отмены/отката. Это поведение можно контролировать, изменяя настройки промежуточной фиксации для движка RocksDB.
Для коллекций с шардированием вся операция запроса и/или замены может не быть транзакционной, особенно если она затрагивает разные шарды и/или DB-серверы.