1
0
Fork 0

Docs: Access current/OLD value in UPDATE

This commit is contained in:
Simran Brucherseifer 2016-08-22 18:34:26 +02:00
parent a542735683
commit 1e6503d1e0
1 changed files with 91 additions and 23 deletions

View File

@ -23,17 +23,17 @@ be updated. *document* must be a document that contains the attributes and value
to be updated. When using the first syntax, *document* must also contain the *_key*
attribute to identify the document to be updated.
```
```js
FOR u IN users
UPDATE { _key: u._key, name: CONCAT(u.firstName, u.lastName) } IN users
UPDATE { _key: u._key, name: CONCAT(u.firstName, " ", u.lastName) } IN users
```
The following query is invalid because it does not contain a *_key* attribute and
thus it is not possible to determine the documents to be updated:
```
```js
FOR u IN users
UPDATE { name: CONCAT(u.firstName, u.lastName) } IN users
UPDATE { name: CONCAT(u.firstName, " ", u.lastName) } IN users
```
When using the second syntax, *keyExpression* provides the document identification.
@ -42,21 +42,21 @@ document, which must contain a *_key* attribute.
The following queries are equivalent:
```
```js
FOR u IN users
UPDATE u._key WITH { name: CONCAT(u.firstName, u.lastName) } IN users
UPDATE u._key WITH { name: CONCAT(u.firstName, " ", u.lastName) } IN users
FOR u IN users
UPDATE { _key: u._key } WITH { name: CONCAT(u.firstName, u.lastName) } IN users
UPDATE { _key: u._key } WITH { name: CONCAT(u.firstName, " ", u.lastName) } IN users
FOR u IN users
UPDATE u WITH { name: CONCAT(u.firstName, u.lastName) } IN users
UPDATE u WITH { name: CONCAT(u.firstName, " ", u.lastName) } IN users
```
An update operation may update arbitrary documents which do not need to be identical
to the ones produced by a preceding *FOR* statement:
```
```js
FOR i IN 1..1000
UPDATE CONCAT('test', i) WITH { foobar: true } IN users
@ -65,14 +65,74 @@ FOR u IN users
UPDATE u WITH { status: 'inactive' } IN backup
```
!SUBSECTION Using the current value of a document attribute
The pseudo-variable `OLD` is not supported inside of `WITH` clauses (it is
available after `UPDATE`). To access the current attribute value, you can
usually refer to a document via the variable of the `FOR` loop, which is used
to iterate over a collection:
```js
FOR doc IN users
UPDATE doc WITH {
fullName: CONCAT(doc.firstName, " ", doc.lastName)
} IN users
```
If there is no loop, because a single document is updated only, then there
might not be a variable like above (`doc`), which would let you refer to the
document which is being updated:
```js
UPDATE "users/john" WITH { ... } IN users
```
To access the current value in this situation, the document has to be retrieved
and stored in a variable first:
```js
LET doc = DOCUMENT("users/john")
UPDATE doc WITH {
fullName: CONCAT(doc.firstName, " ", doc.lastName)
} IN users
```
An existing attribute can be modified based on its current value this way,
to increment a counter for instance:
```js
UPDATE doc WITH {
karma: doc.karma + 1
} IN users
```
If the attribute `karma` doesn't exist yet, `doc.karma` is evaluated to *null*.
The expression `null + 1` results in the new attribute `karma` being set to *1*.
If the attribute does exist, then it is increased by *1*.
Arrays can be mutated too of course:
```js
UPDATE doc WITH {
hobbies: PUSH(doc.hobbies, "swimming")
} IN users
```
If the attribute `hobbies` doesn't exist yet, it is conveniently initialized
as `[ "swimming" ]` and otherwise extended.
!SUBSECTION Setting query options
*options* can be used to suppress query errors that may occur when trying to
update non-existing documents or violating unique key constraints:
```
```js
FOR i IN 1..1000
UPDATE { _key: CONCAT('test', i) } WITH { foobar: true } IN users OPTIONS { ignoreErrors: true }
UPDATE {
_key: CONCAT('test', i)
} WITH {
foobar: true
} IN users OPTIONS { ignoreErrors: true }
```
An update operation will only update the attributes specified in *document* and
@ -84,9 +144,12 @@ When updating an attribute with a null value, ArangoDB will not remove the attri
from the document but store a null value for it. To get rid of attributes in an update
operation, set them to null and provide the *keepNull* option:
```
```js
FOR u IN users
UPDATE u WITH { foobar: true, notNeeded: null } IN users OPTIONS { keepNull: false }
UPDATE u WITH {
foobar: true,
notNeeded: null
} IN users OPTIONS { keepNull: false }
```
The above query will remove the *notNeeded* attribute from the documents and update
@ -100,17 +163,21 @@ The following query will set the updated document's *name* attribute to the exac
same value that is specified in the query. This is due to the *mergeObjects* option
being set to *false*:
```
```js
FOR u IN users
UPDATE u WITH { name: { first: "foo", middle: "b.", last: "baz" } } IN users OPTIONS { mergeObjects: false }
UPDATE u WITH {
name: { first: "foo", middle: "b.", last: "baz" }
} IN users OPTIONS { mergeObjects: false }
```
Contrary, the following query will merge the contents of the *name* attribute in the
original document with the value specified in the query:
```
```js
FOR u IN users
UPDATE u WITH { name: { first: "foo", middle: "b.", last: "baz" } } IN users OPTIONS { mergeObjects: true }
UPDATE u WITH {
name: { first: "foo", middle: "b.", last: "baz" }
} IN users OPTIONS { mergeObjects: true }
```
Attributes in *name* that are present in the to-be-updated document but not in the
@ -123,9 +190,11 @@ explicitly.
To make sure data are durable when an update query returns, there is the *waitForSync*
query option:
```
```js
FOR u IN users
UPDATE u WITH { foobar: true } IN users OPTIONS { waitForSync: true }
UPDATE u WITH {
foobar: true
} IN users OPTIONS { waitForSync: true }
```
!SUBSECTION Returning the modified documents
@ -149,7 +218,7 @@ UPDATE keyExpression WITH document IN collection options RETURN NEW
Following is an example using a variable named `previous` to capture the original
documents before modification. For each modified document, the document key is returned.
```
```js
FOR u IN users
UPDATE u WITH { value: "test" }
LET previous = OLD
@ -159,7 +228,7 @@ FOR u IN users
The following query uses the `NEW` pseudo-value to return the updated documents,
without some of the system attributes:
```
```js
FOR u IN users
UPDATE u WITH { value: "test" }
LET updated = NEW
@ -168,9 +237,8 @@ FOR u IN users
It is also possible to return both `OLD` and `NEW`:
```
```js
FOR u IN users
UPDATE u WITH { value: "test" }
RETURN { before: OLD, after: NEW }
```