diff --git a/site/content/3.12/about-arangodb/features/highlights-by-version.md b/site/content/3.12/about-arangodb/features/highlights-by-version.md index 5156baefa9..a3ebe9bf3c 100644 --- a/site/content/3.12/about-arangodb/features/highlights-by-version.md +++ b/site/content/3.12/about-arangodb/features/highlights-by-version.md @@ -17,6 +17,10 @@ aliases: Accelerate wildcard searches against Views and inverted indexes with _n_-grams to quickly find candidate matches. +- [**External versioning**](../../release-notes/version-3.12/whats-new-in-3-12.md#external-versioning-support): + Specify any top-level attribute to compare whether the version number is higher + than the currently stored one when updating or replacing documents. + **Enterprise Edition** - [**ArangoSearch WAND optimization**](../../index-and-search/arangosearch/performance.md#wand-optimization): diff --git a/site/content/3.12/aql/high-level-operations/insert.md b/site/content/3.12/aql/high-level-operations/insert.md index e39c6765fb..0d954b499c 100644 --- a/site/content/3.12/aql/high-level-operations/insert.md +++ b/site/content/3.12/aql/high-level-operations/insert.md @@ -175,6 +175,39 @@ INSERT { _from: "vert/A", _to: "vert/B" } INTO coll OPTIONS { refillIndexCaches: true } ``` +### `versionAttribute` + +Only applicable if `overwrite` is set to `true` or `overwriteMode` +is set to `update` or `replace`. + +You can use the `versionAttribute` option for external versioning support. +If set, the attribute with the name specified by the option is looked up in the +stored document and the attribute value is compared numerically to the value of +the versioning attribute in the supplied document that is supposed to update/replace it. + +If the version number in the new document is higher (rounded down to a whole number) +than in the document that already exists in the database, then the update/replace +operation is performed normally. This is also the case if the new versioning +attribute has a non-numeric value, if it is a negative number, or if the +attribute doesn't exist in the supplied or stored document. + +If the version number in the new document is lower or equal to what exists in +the database, the operation is not performed and the existing document thus not +changed. No error is returned in this case. + +The attribute can only be a top-level attribute. + +For example, the following query conditionally replaces an existing document with +the key `"123"` if the attribute `externalVersion` currently has a value below `5`: + +```aql +INSERT { _key: "123", externalVersion: 5, anotherAttribute: true } IN coll + OPTIONS { overwriteMode: "replace", versionAttribute: "externalVersion" } +``` + +You can check if `OLD._rev` (if not `null`) and `NEW._rev` are different to determine if the +document has been changed. + ## Returning the inserted documents The inserted documents can also be returned by the query. In this case, the `INSERT` diff --git a/site/content/3.12/aql/high-level-operations/replace.md b/site/content/3.12/aql/high-level-operations/replace.md index bc96d97736..950bf27128 100644 --- a/site/content/3.12/aql/high-level-operations/replace.md +++ b/site/content/3.12/aql/high-level-operations/replace.md @@ -252,6 +252,36 @@ REPLACE { _key: "123", _from: "vert/C", _to: "vert/D" } IN edgeColl OPTIONS { refillIndexCaches: true } ``` +### `versionAttribute` + +You can use the `versionAttribute` option for external versioning support. +If set, the attribute with the name specified by the option is looked up in the +stored document and the attribute value is compared numerically to the value of +the versioning attribute in the supplied document that is supposed to replace it. + +If the version number in the new document is higher (rounded down to a whole number) +than in the document that already exists in the database, then the replace +operation is performed normally. This is also the case if the new versioning +attribute has a non-numeric value, if it is a negative number, or if the +attribute doesn't exist in the supplied or stored document. + +If the version number in the new document is lower or equal to what exists in +the database, the operation is not performed and the existing document thus not +changed. No error is returned in this case. + +The attribute can only be a top-level attribute. + +For example, the following query conditionally replaces an existing document with +the key `"123"` if the attribute `externalVersion` currently has a value below `5`: + +```aql +REPLACE { _key: "123", externalVersion: 5, anotherAttribute: true } IN coll + OPTIONS { versionAttribute: "externalVersion" } +``` + +You can check if `OLD._rev` and `NEW._rev` are different to determine if the +document has been changed. + ## Returning the modified documents You can optionally return the documents modified by the query. In this case, the `REPLACE` diff --git a/site/content/3.12/aql/high-level-operations/update.md b/site/content/3.12/aql/high-level-operations/update.md index 1152ebc56c..6b56a6b2a0 100644 --- a/site/content/3.12/aql/high-level-operations/update.md +++ b/site/content/3.12/aql/high-level-operations/update.md @@ -368,6 +368,36 @@ UPDATE { _key: "123", _from: "vert/C", _to: "vert/D" } IN edgeColl OPTIONS { refillIndexCaches: true } ``` +### `versionAttribute` + +You can use the `versionAttribute` option for external versioning support. +If set, the attribute with the name specified by the option is looked up in the +stored document and the attribute value is compared numerically to the value of +the versioning attribute in the supplied document that is supposed to update it. + +If the version number in the new document is higher (rounded down to a whole number) +than in the document that already exists in the database, then the update +operation is performed normally. This is also the case if the new versioning +attribute has a non-numeric value, if it is a negative number, or if the +attribute doesn't exist in the supplied or stored document. + +If the version number in the new document is lower or equal to what exists in +the database, the operation is not performed and the existing document thus not +changed. No error is returned in this case. + +The attribute can only be a top-level attribute. + +For example, the following query conditionally updates an existing document with +the key `"123"` if the attribute `externalVersion` currently has a value below `5`: + +```aql +UPDATE { _key: "123", externalVersion: 5, anotherAttribute: true } IN coll + OPTIONS { versionAttribute: "externalVersion" } +``` + +You can check if `OLD._rev` and `NEW._rev` are different to determine if the +document has been changed. + ## Returning the modified documents You can optionally return the documents modified by the query. In this case, the `UPDATE` diff --git a/site/content/3.12/develop/http-api/documents.md b/site/content/3.12/develop/http-api/documents.md index 41a3036f20..f9c1488eef 100644 --- a/site/content/3.12/develop/http-api/documents.md +++ b/site/content/3.12/develop/http-api/documents.md @@ -476,6 +476,34 @@ paths: affect the edge index or cache-enabled persistent indexes. schema: type: boolean + - name: versionAttribute + in: query + required: false + description: | + Only applicable if `overwrite` is set to `true` or `overwriteMode` + is set to `update` or `replace`. + + You can use the `versionAttribute` option for external versioning support. + If set, the attribute with the name specified by the option is looked up in the + stored document and the attribute value is compared numerically to the value of + the versioning attribute in the supplied document that is supposed to update/replace it. + + If the version number in the new document is higher (rounded down to a whole number) + than in the document that already exists in the database, then the update/replace + operation is performed normally. This is also the case if the new versioning + attribute has a non-numeric value, if it is a negative number, or if the + attribute doesn't exist in the supplied or stored document. + + If the version number in the new document is lower or equal to what exists in + the database, the operation is not performed and the existing document thus not + changed. No error is returned in this case. + + The attribute can only be a top-level attribute. + + You can check if `_oldRev` (if present) and `_rev` are different to determine if the + document has been changed. + schema: + type: string - name: x-arango-trx-id in: header required: false @@ -856,6 +884,31 @@ paths: replacements affect the edge index or cache-enabled persistent indexes. schema: type: boolean + - name: versionAttribute + in: query + required: false + description: | + You can use the `versionAttribute` option for external versioning support. + If set, the attribute with the name specified by the option is looked up in the + stored document and the attribute value is compared numerically to the value of + the versioning attribute in the supplied document that is supposed to replace it. + + If the version number in the new document is higher (rounded down to a whole number) + than in the document that already exists in the database, then the replace + operation is performed normally. This is also the case if the new versioning + attribute has a non-numeric value, if it is a negative number, or if the + attribute doesn't exist in the supplied or stored document. + + If the version number in the new document is lower or equal to what exists in + the database, the operation is not performed and the existing document thus not + changed. No error is returned in this case. + + The attribute can only be a top-level attribute. + + You can check if `_oldRev` and `_rev` are different to determine if the + document has been changed. + schema: + type: string - name: If-Match in: header required: false @@ -1178,6 +1231,31 @@ paths: affect the edge index or cache-enabled persistent indexes. schema: type: boolean + - name: versionAttribute + in: query + required: false + description: | + You can use the `versionAttribute` option for external versioning support. + If set, the attribute with the name specified by the option is looked up in the + stored document and the attribute value is compared numerically to the value of + the versioning attribute in the supplied document that is supposed to update it. + + If the version number in the new document is higher (rounded down to a whole number) + than in the document that already exists in the database, then the update + operation is performed normally. This is also the case if the new versioning + attribute has a non-numeric value, if it is a negative number, or if the + attribute doesn't exist in the supplied or stored document. + + If the version number in the new document is lower or equal to what exists in + the database, the operation is not performed and the existing document thus not + changed. No error is returned in this case. + + The attribute can only be a top-level attribute. + + You can check if `_oldRev` and `_rev` are different to determine if the + document has been changed. + schema: + type: string - name: If-Match in: header required: false @@ -1875,6 +1953,34 @@ paths: affect the edge index or cache-enabled persistent indexes. schema: type: boolean + - name: versionAttribute + in: query + required: false + description: | + Only applicable if `overwrite` is set to `true` or `overwriteMode` + is set to `update` or `replace`. + + You can use the `versionAttribute` option for external versioning support. + If set, the attribute with the name specified by the option is looked up in the + stored document and the attribute value is compared numerically to the value of + the versioning attribute in the supplied document that is supposed to update/replace it. + + If the version number in the new document is higher (rounded down to a whole number) + than in the document that already exists in the database, then the update/replace + operation is performed normally. This is also the case if the new versioning + attribute has a non-numeric value, if it is a negative number, or if the + attribute doesn't exist in the supplied or stored document. + + If the version number in the new document is lower or equal to what exists in + the database, the operation is not performed and the existing document thus not + changed. No error is returned in this case. + + The attribute can only be a top-level attribute. + + You can check if `_oldRev` (if present) and `_rev` are different to determine if the + document has been changed. + schema: + type: string - name: x-arango-trx-id in: header required: false @@ -2146,6 +2252,31 @@ paths: replacements affect the edge index or cache-enabled persistent indexes. schema: type: boolean + - name: versionAttribute + in: query + required: false + description: | + You can use the `versionAttribute` option for external versioning support. + If set, the attribute with the name specified by the option is looked up in the + stored document and the attribute value is compared numerically to the value of + the versioning attribute in the supplied document that is supposed to replace it. + + If the version number in the new document is higher (rounded down to a whole number) + than in the document that already exists in the database, then the replace + operation is performed normally. This is also the case if the new versioning + attribute has a non-numeric value, if it is a negative number, or if the + attribute doesn't exist in the supplied or stored document. + + If the version number in the new document is lower or equal to what exists in + the database, the operation is not performed and the existing document thus not + changed. No error is returned in this case. + + The attribute can only be a top-level attribute. + + You can check if `_oldRev` and `_rev` are different to determine if the + document has been changed. + schema: + type: string - name: x-arango-trx-id in: header required: false @@ -2368,6 +2499,31 @@ paths: affect the edge index or cache-enabled persistent indexes. schema: type: boolean + - name: versionAttribute + in: query + required: false + description: | + You can use the `versionAttribute` option for external versioning support. + If set, the attribute with the name specified by the option is looked up in the + stored document and the attribute value is compared numerically to the value of + the versioning attribute in the supplied document that is supposed to update it. + + If the version number in the new document is higher (rounded down to a whole number) + than in the document that already exists in the database, then the update + operation is performed normally. This is also the case if the new versioning + attribute has a non-numeric value, if it is a negative number, or if the + attribute doesn't exist in the supplied or stored document. + + If the version number in the new document is lower or equal to what exists in + the database, the operation is not performed and the existing document thus not + changed. No error is returned in this case. + + The attribute can only be a top-level attribute. + + You can check if `_oldRev` and `_rev` are different to determine if the + document has been changed. + schema: + type: string - name: x-arango-trx-id in: header required: false diff --git a/site/content/3.12/develop/javascript-api/@arangodb/collection-object.md b/site/content/3.12/develop/javascript-api/@arangodb/collection-object.md index 523dfd866b..1c5b33d663 100644 --- a/site/content/3.12/develop/javascript-api/@arangodb/collection-object.md +++ b/site/content/3.12/develop/javascript-api/@arangodb/collection-object.md @@ -996,6 +996,28 @@ used to specify the following options: existing document's value. If set to `true`, objects will be merged. The default is `true`. This option controls the update-insert behavior only. +- `versionAttribute`: Only applicable if `overwrite` is set to `true` or + `overwriteMode` is set to `update` or `replace`. + + You can use the `versionAttribute` option for external versioning support. + If set, the attribute with the name specified by the option is looked up in the + stored document and the attribute value is compared numerically to the value of + the versioning attribute in the supplied document that is supposed to update/replace it. + + If the version number in the new document is higher (rounded down to a whole number) + than in the document that already exists in the database, then the update/replace + operation is performed normally. This is also the case if the new versioning + attribute has a non-numeric value, if it is a negative number, or if the + attribute doesn't exist in the supplied or stored document. + + If the version number in the new document is lower or equal to what exists in + the database, the operation is not performed and the existing document thus not + changed. No error is returned in this case. + + The attribute can only be a top-level attribute. + + You can check if `_oldRev` (if present) and `_rev` are different to determine if the + document has been changed. --- @@ -1301,7 +1323,26 @@ Replaces an existing document, with additional options passed as an object: revision of the document is returned in the output under the attribute `old`. - `silent`: If this flag is set to `true`, no output is returned. +- `versionAttribute`: + You can use the `versionAttribute` option for external versioning support. + If set, the attribute with the name specified by the option is looked up in the + stored document and the attribute value is compared numerically to the value of + the versioning attribute in the supplied document that is supposed to replace it. + + If the version number in the new document is higher (rounded down to a whole number) + than in the document that already exists in the database, then the replace + operation is performed normally. This is also the case if the new versioning + attribute has a non-numeric value, if it is a negative number, or if the + attribute doesn't exist in the supplied or stored document. + + If the version number in the new document is lower or equal to what exists in + the database, the operation is not performed and the existing document thus not + changed. No error is returned in this case. + + The attribute can only be a top-level attribute. + You can check if `_oldRev` and `_rev` are different to determine if the + document has been changed. --- `collection.replace(document-identifier, data [, options])` @@ -1473,6 +1514,26 @@ an object: set to `false`, the value in the patch document will overwrite the existing document's value. If set to `true`, objects will be merged. The default is `true`. +- `versionAttribute`: + You can use the `versionAttribute` option for external versioning support. + If set, the attribute with the name specified by the option is looked up in the + stored document and the attribute value is compared numerically to the value of + the versioning attribute in the supplied document that is supposed to update it. + + If the version number in the new document is higher (rounded down to a whole number) + than in the document that already exists in the database, then the update + operation is performed normally. This is also the case if the new versioning + attribute has a non-numeric value, if it is a negative number, or if the + attribute doesn't exist in the supplied or stored document. + + If the version number in the new document is lower or equal to what exists in + the database, the operation is not performed and the existing document thus not + changed. No error is returned in this case. + + The attribute can only be a top-level attribute. + + You can check if `_oldRev` and `_rev` are different to determine if the + document has been changed. --- diff --git a/site/content/3.12/release-notes/version-3.12/api-changes-in-3-12.md b/site/content/3.12/release-notes/version-3.12/api-changes-in-3-12.md index cdc6638434..ac796d68ea 100644 --- a/site/content/3.12/release-notes/version-3.12/api-changes-in-3-12.md +++ b/site/content/3.12/release-notes/version-3.12/api-changes-in-3-12.md @@ -257,6 +257,24 @@ and defaults to `[]`. See the [`optimizeTopK` View property](../../index-and-search/arangosearch/arangosearch-views-reference.md#view-properties) for details. +#### Document API + +The following endpoints accept a new `versionAttribute` query parameter that adds +external versioning support: + +- `PATCH /_api/document/{collection}/{key}` (single document update) +- `PATCH /_api/document/{collection}` (multiple document update) +- `PUT /_api/document/{collection}` (single document replace) +- `PUT /_api/document/{collection}/{key}` (multiple document replace) +- `POST /_api/document/{collection}` (single document insert, when used to update/replace a document) +- `POST /_api/document/{collection}/{key}` (multiple document insert, when used to update/replace a document) + +If set, the attribute with the name specified by the option is looked up in the +stored document and the attribute value is compared numerically to the value of +the versioning attribute in the supplied document that is supposed to update/replace it. +The document is only changed if the new number is higher. See the +[Document API](../../develop/http-api/documents.md#create-a-document) for details. + #### Index API ##### `optimizeTopK` for inverted indexes @@ -431,7 +449,23 @@ not handle larger amounts of data and were thus very limited. Users of the JavaScript-based traversal API should use [AQL traversal queries](../../aql/graphs/traversals.md) instead. +### `collection` object + +The following methods now accept a `versionAttribute` option that adds external +versioning support: + +- `collection.update(object, data, options)` +- `collection.replace(object, data, options)` +- `collection.insert(data, options)` when used to update/replace a document + +If set, the attribute with the name specified by the option is looked up in the +stored document and the attribute value is compared numerically to the value of +the versioning attribute in the supplied document that is supposed to update/replace it. +The document is only changed if the new number is higher. See the +[JavaScript API](../../develop/javascript-api/@arangodb/collection-object.md#collectioninsertdata--options) +for details. + ### `@arangodb/pregel` package The `@arangodb/pregel` JavaScript API package has been removed in v3.12.0 and -will no longer be supported. \ No newline at end of file +will no longer be supported. diff --git a/site/content/3.12/release-notes/version-3.12/whats-new-in-3-12.md b/site/content/3.12/release-notes/version-3.12/whats-new-in-3-12.md index c2cd97eb3e..66311a2f3e 100644 --- a/site/content/3.12/release-notes/version-3.12/whats-new-in-3-12.md +++ b/site/content/3.12/release-notes/version-3.12/whats-new-in-3-12.md @@ -176,6 +176,83 @@ section, as well as in the **API** tab of Foxx services and Foxx routes that use The new version adds support for OpenAPI 3.x specifications in addition to Swagger 2.x compatibility. +## External versioning support + +Document operations that update or replace documents now support a `versionAttribute` option. +If set, the attribute with the name specified by the option is looked up in the +stored document and the attribute value is compared numerically to the value of +the versioning attribute in the supplied document that is supposed to update/replace it. +The document is only changed if the new number is higher. + +This simple versioning can help to avoid overwriting existing data with older +versions in case data is transferred from an external system into ArangoDB +and the copies are currently not in sync. + +This new feature is supported in AQL, the JavaScript API, and the HTTP API for +the respective operations to update and replace documents, including the insert +operations when used to update/replace a document with `overwriteMode: "update"` +or `overwriteMode: "replace"`. + +**Examples:** + +Insert a new document normally using _arangosh_: + +```js +db.collection.insert({ _key: "123", externalVersion: 1 }); +``` + +Update the document if the versioning attribute is higher in the new document, +which is true in this case: + +```js +db.collection.update("123", + { externalVersion: 5, anotherAttribute: true }, + { versionAttribute: "externalVersion" }); +``` + +Updating the document is skipped if the versioning attribute is lower or equal +in the supplied document compared to what is currently stored in ArangoDB: + +```js +db.collection.update("123", + { externalVersion: 4, anotherAttribute: false }, + { versionAttribute: "externalVersion" }); +``` + +You can also make use of the `versionAttribute` option in an insert-update +operation for the update case, including in AQL: + +```js +db.collection.insert({ _key: "123", externalVersion: 6, value: "foo" }, + { overwriteMode: "update", versionAttribute: "externalVersion" }); + +db._query(`UPDATE { _key: "123", externalVersion: 7, value: "bar" } IN collection + OPTIONS { versionAttribute: "externalVersion"}`); +``` + +External versioning is opt-in and no version checking is performed for +operations for which the `versionAttribute` option isn't set. Document removal +operations do not support external versioning. Removal operations are always +carried out normally. + +Note that version checking is performed only if both the existing version of +the document in the database and the new document version contain the version +attribute with numeric values of `0` or greater. If neither the existing document +in the database nor the new document contains the version attribute, or if the +version attribute in any of the two is not a number inside the valid range, the +update/replace operations behave as if no version checking was requested. +This may overwrite the versioning attribute in the database. + +Also see: +- The AQL [INSERT](../../aql/high-level-operations/insert.md#versionattribute), + [UPDATE](../../aql/high-level-operations/update.md#versionattribute) and + [REPLACE](../../aql/high-level-operations/update.md#versionattribute) operations +- The `insert()`, `update()`, `replace()` methods of the + [_collection_ object](../../develop/javascript-api/@arangodb/collection-object.md#collectioninsertdata--options) + in the JavaScript API +- The endpoints to create, update, and replace a single or multiple documents + in the [HTTP API](../../develop/javascript-api/@arangodb/collection-object.md#collectioninsertdata--options) + ## AQL ### Improved joins