Skip to content

Commit 2571a2e

Browse files
nerpaulajsteemannSimran-B
authored
DOC-625 | Alternative UPSERT syntax with filter conditions (#349)
* alternative UPSERT syntax with filter conditions * finalize description and examples * Apply suggestions from code review Co-authored-by: Jan <[email protected]> * change naming > more flexible filter conditions * Review, improve example, mention index utilization, inverted index cannot be used * Remove incorrect statement --------- Co-authored-by: Jan <[email protected]> Co-authored-by: Simran Spiller <[email protected]>
1 parent 29b317b commit 2571a2e

File tree

4 files changed

+210
-83
lines changed

4 files changed

+210
-83
lines changed

site/content/3.10/aql/high-level-operations/upsert.md

Lines changed: 38 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,16 @@ title: '`UPSERT` operation in AQL'
33
menuTitle: UPSERT
44
weight: 70
55
description: >-
6-
The `UPSERT` operations either modifies an existing document, or creates a new
6+
An `UPSERT` operation either modifies an existing document, or creates a new
77
document if it does not exist
88
archetype: default
99
---
10+
`UPSERT` looks up a single document that matches the provided example.
11+
If there is no match, an insert operation is executed to create a
12+
document. If a document is found, you can either update or replace the document.
13+
These subtypes are called **upsert** (update or insert) and **repsert**
14+
(replace or insert).
15+
1016
Each `UPSERT` operation is restricted to a single collection, and the
1117
[collection name](../../concepts/data-structure/collections.md#collection-names) must not be dynamic.
1218
Only a single `UPSERT` statement per collection is allowed per AQL query, and
@@ -15,44 +21,47 @@ traversal operations, or AQL functions that can read documents.
1521

1622
## Syntax
1723

18-
The syntax for upsert and repsert operations is:
24+
The syntax for an upsert operation:
1925

2026
<pre><code>UPSERT <em>searchExpression</em>
2127
INSERT <em>insertExpression</em>
2228
UPDATE <em>updateExpression</em>
2329
IN <em>collection</em></code></pre>
2430

31+
The syntax for a repsert operation:
32+
2533
<pre><code>UPSERT <em>searchExpression</em>
2634
INSERT <em>insertExpression</em>
2735
REPLACE <em>updateExpression</em>
2836
IN <em>collection</em></code></pre>
2937

3038
Both variants can optionally end with an `OPTIONS { … }` clause.
3139

32-
When using the `UPDATE` variant of the upsert operation, the found document
33-
will be partially updated, meaning only the attributes specified in
34-
*updateExpression* will be updated or added. When using the `REPLACE` variant
35-
of upsert (repsert), existing documents will be replaced with the contexts of
40+
When using the `UPDATE` variant of the `UPSERT` operation, the found document
41+
is partially updated, meaning only the attributes specified in
42+
*updateExpression* are updated or added. When using the `REPLACE` variant
43+
of `UPSERT` (repsert), the found document is replaced with the content of
3644
*updateExpression*.
3745

38-
Updating a document will modify the document's revision number with a server-generated value.
39-
The system attributes `_id`, `_key` and `_rev` cannot be updated, `_from` and `_to` can.
46+
Updating a document modifies the document's revision number with a server-generated value.
47+
The system attributes `_id`, `_key`, and `_rev` cannot be updated, but `_from` and `_to`
48+
can be modified.
4049

41-
The *searchExpression* contains the document to be looked for. It must be an object
42-
literal without dynamic attribute names. In case no such document can be found in
43-
*collection*, a new document will be inserted into the collection as specified in the
44-
*insertExpression*.
50+
The *searchExpression* contains the document to be looked for. It must be an
51+
**object literal** (`UPSERT { <key>: <value>, ... } ...`) without dynamic
52+
attribute names. In case no such document can be found in *collection*, a new
53+
document is inserted into the collection as specified in the *insertExpression*.
4554

46-
In case at least one document in *collection* matches the *searchExpression*, it will
47-
be updated using the *updateExpression*. When more than one document in the collection
48-
matches the *searchExpression*, it is undefined which of the matching documents will
49-
be updated. It is therefore often sensible to make sure by other means (such as unique
55+
In case at least one document in *collection* matches the *searchExpression*, it is
56+
updated using the *updateExpression*. When more than one document in the collection
57+
matches the *searchExpression*, it is undefined which of the matching documents is
58+
updated. It is therefore often sensible to make sure by other means (such as unique
5059
indexes, application logic etc.) that at most one document matches *searchExpression*.
5160

52-
The following query will look in the *users* collection for a document with a specific
53-
*name* attribute value. If the document exists, its *logins* attribute will be increased
54-
by one. If it does not exist, a new document will be inserted, consisting of the
55-
attributes *name*, *logins*, and *dateCreated*:
61+
The following query looks for a document in the `users` collection with a specific
62+
`name` attribute value. If the document exists, its *logins* attribute is increased
63+
by one. If it does not exist, a new document is inserted, consisting of the
64+
attributes `name`, `logins`, and `dateCreated`:
5665

5766
```aql
5867
UPSERT { name: 'superuser' }
@@ -96,7 +105,7 @@ inside of arrays (e.g. `{ attr: [ { nested: null } ] }`).
96105

97106
### `mergeObjects`
98107

99-
The option `mergeObjects` controls whether object contents will be
108+
The option `mergeObjects` controls whether object contents are
100109
merged if an object attribute is present in both the `UPDATE` query and in the
101110
to-be-updated document.
102111

@@ -125,9 +134,9 @@ FOR i IN 1..1000
125134
```
126135

127136
{{< info >}}
128-
You need to add the `_rev` value in the *updateExpression*. It will not be used
137+
You need to add the `_rev` value in the *updateExpression*. It is not used
129138
within the *searchExpression*. Even worse, if you use an outdated `_rev` in the
130-
*searchExpression*, `UPSERT` will trigger the `INSERT` path instead of the
139+
*searchExpression*, `UPSERT` triggers the `INSERT` path instead of the
131140
`UPDATE` path, because it has not found a document exactly matching the
132141
*searchExpression*.
133142
{{< /info >}}
@@ -153,7 +162,7 @@ FOR i IN 1..1000
153162

154163
### `indexHint`
155164

156-
The `indexHint` option will be used as a hint for the document lookup
165+
The `indexHint` option is used as a hint for the document lookup
157166
performed as part of the `UPSERT` operation, and can help in cases such as
158167
`UPSERT` not picking the best index automatically.
159168

@@ -167,6 +176,8 @@ UPSERT { a: 1234 }
167176
The index hint is passed through to an internal `FOR` loop that is used for the
168177
lookup. Also see [`indexHint` Option of the `FOR` Operation](for.md#indexhint).
169178

179+
Inverted indexes cannot be used for `UPSERT` lookups.
180+
170181
### `forceIndexHint`
171182

172183
Makes the index or indexes specified in `indexHint` mandatory if enabled. The
@@ -185,11 +196,11 @@ UPSERT { a: 1234 }
185196
`UPSERT` statements can optionally return data. To do so, they need to be followed
186197
by a `RETURN` statement (intermediate `LET` statements are allowed, too). These statements
187198
can optionally perform calculations and refer to the pseudo-values `OLD` and `NEW`.
188-
In case the upsert performed an insert operation, `OLD` will have a value of `null`.
189-
In case the upsert performed an update or replace operation, `OLD` will contain the
199+
In case the upsert performed an insert operation, `OLD` has a value of `null`.
200+
In case the upsert performed an update or replace operation, `OLD` contains the
190201
previous version of the document, before update/replace.
191202

192-
`NEW` will always be populated. It will contain the inserted document in case the
203+
`NEW` is always populated. It contains the inserted document in case the
193204
upsert performed an insert, or the updated/replaced document in case it performed an
194205
update/replace.
195206

site/content/3.11/aql/high-level-operations/upsert.md

Lines changed: 38 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,16 @@ title: '`UPSERT` operation in AQL'
33
menuTitle: UPSERT
44
weight: 70
55
description: >-
6-
The `UPSERT` operations either modifies an existing document, or creates a new
6+
An `UPSERT` operation either modifies an existing document, or creates a new
77
document if it does not exist
88
archetype: default
99
---
10+
`UPSERT` looks up a single document that matches the provided example.
11+
If there is no match, an insert operation is executed to create a
12+
document. If a document is found, you can either update or replace the document.
13+
These subtypes are called **upsert** (update or insert) and **repsert**
14+
(replace or insert).
15+
1016
Each `UPSERT` operation is restricted to a single collection, and the
1117
[collection name](../../concepts/data-structure/collections.md#collection-names) must not be dynamic.
1218
Only a single `UPSERT` statement per collection is allowed per AQL query, and
@@ -15,44 +21,47 @@ traversal operations, or AQL functions that can read documents.
1521

1622
## Syntax
1723

18-
The syntax for upsert and repsert operations is:
24+
The syntax for an upsert operation:
1925

2026
<pre><code>UPSERT <em>searchExpression</em>
2127
INSERT <em>insertExpression</em>
2228
UPDATE <em>updateExpression</em>
2329
IN <em>collection</em></code></pre>
2430

31+
The syntax for a repsert operation:
32+
2533
<pre><code>UPSERT <em>searchExpression</em>
2634
INSERT <em>insertExpression</em>
2735
REPLACE <em>updateExpression</em>
2836
IN <em>collection</em></code></pre>
2937

3038
Both variants can optionally end with an `OPTIONS { … }` clause.
3139

32-
When using the `UPDATE` variant of the upsert operation, the found document
33-
will be partially updated, meaning only the attributes specified in
34-
*updateExpression* will be updated or added. When using the `REPLACE` variant
35-
of upsert (repsert), existing documents will be replaced with the contexts of
40+
When using the `UPDATE` variant of the `UPSERT` operation, the found document
41+
is partially updated, meaning only the attributes specified in
42+
*updateExpression* are updated or added. When using the `REPLACE` variant
43+
of `UPSERT` (repsert), the found document is replaced with the content of
3644
*updateExpression*.
3745

38-
Updating a document will modify the document's revision number with a server-generated value.
39-
The system attributes `_id`, `_key` and `_rev` cannot be updated, `_from` and `_to` can.
46+
Updating a document modifies the document's revision number with a server-generated value.
47+
The system attributes `_id`, `_key`, and `_rev` cannot be updated, but `_from` and `_to`
48+
can be modified.
4049

41-
The *searchExpression* contains the document to be looked for. It must be an object
42-
literal without dynamic attribute names. In case no such document can be found in
43-
*collection*, a new document will be inserted into the collection as specified in the
44-
*insertExpression*.
50+
The *searchExpression* contains the document to be looked for. It must be an
51+
**object literal** (`UPSERT { <key>: <value>, ... } ...`) without dynamic
52+
attribute names. In case no such document can be found in *collection*, a new
53+
document is inserted into the collection as specified in the *insertExpression*.
4554

46-
In case at least one document in *collection* matches the *searchExpression*, it will
47-
be updated using the *updateExpression*. When more than one document in the collection
48-
matches the *searchExpression*, it is undefined which of the matching documents will
49-
be updated. It is therefore often sensible to make sure by other means (such as unique
55+
In case at least one document in *collection* matches the *searchExpression*, it is
56+
updated using the *updateExpression*. When more than one document in the collection
57+
matches the *searchExpression*, it is undefined which of the matching documents is
58+
updated. It is therefore often sensible to make sure by other means (such as unique
5059
indexes, application logic etc.) that at most one document matches *searchExpression*.
5160

52-
The following query will look in the *users* collection for a document with a specific
53-
*name* attribute value. If the document exists, its *logins* attribute will be increased
54-
by one. If it does not exist, a new document will be inserted, consisting of the
55-
attributes *name*, *logins*, and *dateCreated*:
61+
The following query looks for a document in the `users` collection with a specific
62+
`name` attribute value. If the document exists, its *logins* attribute is increased
63+
by one. If it does not exist, a new document is inserted, consisting of the
64+
attributes `name`, `logins`, and `dateCreated`:
5665

5766
```aql
5867
UPSERT { name: 'superuser' }
@@ -96,7 +105,7 @@ inside of arrays (e.g. `{ attr: [ { nested: null } ] }`).
96105

97106
### `mergeObjects`
98107

99-
The option `mergeObjects` controls whether object contents will be
108+
The option `mergeObjects` controls whether object contents are
100109
merged if an object attribute is present in both the `UPDATE` query and in the
101110
to-be-updated document.
102111

@@ -125,9 +134,9 @@ FOR i IN 1..1000
125134
```
126135

127136
{{< info >}}
128-
You need to add the `_rev` value in the *updateExpression*. It will not be used
137+
You need to add the `_rev` value in the *updateExpression*. It is not used
129138
within the *searchExpression*. Even worse, if you use an outdated `_rev` in the
130-
*searchExpression*, `UPSERT` will trigger the `INSERT` path instead of the
139+
*searchExpression*, `UPSERT` triggers the `INSERT` path instead of the
131140
`UPDATE` path, because it has not found a document exactly matching the
132141
*searchExpression*.
133142
{{< /info >}}
@@ -153,7 +162,7 @@ FOR i IN 1..1000
153162

154163
### `indexHint`
155164

156-
The `indexHint` option will be used as a hint for the document lookup
165+
The `indexHint` option is used as a hint for the document lookup
157166
performed as part of the `UPSERT` operation, and can help in cases such as
158167
`UPSERT` not picking the best index automatically.
159168

@@ -167,6 +176,8 @@ UPSERT { a: 1234 }
167176
The index hint is passed through to an internal `FOR` loop that is used for the
168177
lookup. Also see [`indexHint` Option of the `FOR` Operation](for.md#indexhint).
169178

179+
Inverted indexes cannot be used for `UPSERT` lookups.
180+
170181
### `forceIndexHint`
171182

172183
Makes the index or indexes specified in `indexHint` mandatory if enabled. The
@@ -185,11 +196,11 @@ UPSERT { a: 1234 }
185196
`UPSERT` statements can optionally return data. To do so, they need to be followed
186197
by a `RETURN` statement (intermediate `LET` statements are allowed, too). These statements
187198
can optionally perform calculations and refer to the pseudo-values `OLD` and `NEW`.
188-
In case the upsert performed an insert operation, `OLD` will have a value of `null`.
189-
In case the upsert performed an update or replace operation, `OLD` will contain the
199+
In case the upsert performed an insert operation, `OLD` has a value of `null`.
200+
In case the upsert performed an update or replace operation, `OLD` contains the
190201
previous version of the document, before update/replace.
191202

192-
`NEW` will always be populated. It will contain the inserted document in case the
203+
`NEW` is always populated. It contains the inserted document in case the
193204
upsert performed an insert, or the updated/replaced document in case it performed an
194205
update/replace.
195206

0 commit comments

Comments
 (0)