1
0
Fork 0
arangodb/Documentation/Books/Users/Aql/DataModification.mdpp

180 lines
6.8 KiB
Plaintext

!CHAPTER Data Modification Queries
AQL supports the following data-modification operations:
- **INSERT**: insert new documents into a collection
- **UPDATE**: partially update existing documents in a collection
- **REPLACE**: completely replace existing documents in a collection
- **REMOVE**: remove existing documents from a collection
- **UPSERT**: conditionally insert or update documents in a collection
Those operations are detailed in the chapter [High Level Operations](Operations.md).
!SUBSECTION Modifying a single document
Let's start with the basics: `INSERT`, `UPDATE` and `REMOVE` operations on single documents.
Here is an example that insert a document in an existing collection *users*:
INSERT {firstName:'Anna', name:'Pavlova', profession:'artist'} IN users
You may provide a key for the new document; if not provided, ArangoDB will create one for you.
INSERT {_key:'GilbertoGil', firstName:'Gilberto', name:'Gil', city:'Fortalezza'} IN users
As Arango is schema-free, attributes of the documents may vary:
INSERT {_key:'PhilCarpenter', firstName:'Phil', name:'Carpenter', middleName:'G.',status:'inactive', } IN users
INSERT {_key:'NatachaDeclerck', firstName:'Natacha', name:'Declerck', location:'Antwerp'} IN users
Update is quite simple. The following AQL statement will add or change the attributes status and location
UPDATE 'PhilCarpenter' WITH { status:'active', location:'Beijing' } IN users
Replace is an alternative to update where all attributes of the document are replaced.
REPLACE { _key: 'NatachaDeclerck', firstName:'Natacha', name:'Leclerc', status: 'active', level:'premium' } IN users
Removing a document if you know its key is simple as well :
REMOVE 'GilbertoGil' IN users
or
REMOVE {_key:'GilbertoGil'} IN users
!SUBSECTION Modifying multiple documents
Data-modification operations are normally combined with *FOR* loops to
iterate over a given list of documents. They can optionally be combined with
*FILTER* statements and the like.
Let's start with an example that modifies existing documents in a collection
*users* that match some condition:
FOR u IN users
FILTER u.status == 'not active'
UPDATE u WITH { status: 'inactive' } IN users
Now, let's copy the contents of the collection *users* into the collection
*backup*:
FOR u IN users
INSERT u IN backup
As a final example, let's find some documents in collection *users* and
remove them from collection *backup*. The link between the documents in both
collections is established via the documents' keys:
FOR u IN users
FILTER u.status == 'deleted'
REMOVE u IN backup
!SUBSECTION Returning documents
Data-modification queries can optionally return documents. In order to reference
the inserted, removed or modified documents in a `RETURN` statement, data-modification
statements introduce the `OLD` and/or `NEW` pseudo-values:
FOR i IN 1..100
INSERT { value: i } IN test
RETURN NEW
FOR u IN users
FILTER u.status == 'deleted'
REMOVE u IN users
RETURN OLD
FOR u IN users
FILTER u.status == 'not active'
UPDATE u WITH { status: 'inactive' } IN users
RETURN NEW
`NEW` refers to the inserted or modified document revision, and `OLD` refers
to the document revision before update or removal. `INSERT` statements can
only refer to the `NEW` pseudo-value, and `REMOVE` operations only to `OLD`.
`UPDATE`, `REPLACE` and `UPSERT` can refer to either.
In all cases the full documents will be returned with all their attributes,
including the potentially auto-generated attributes such as `_id`, `_key`, or `_rev`
and the attributes not specified in the update expression of a partial update.
!SUBSUBSECTION Projections
It is possible to return a projection of the documents in `OLD` or `NEW` instead of
returning the entire documents. This can be used to reduce the amount of data returned
by queries.
For example, the following query will return only the keys of the inserted documents:
FOR i IN 1..100
INSERT { value: i } IN test
RETURN NEW._key
!SUBSUBSECTION Using OLD and NEW in the same query
For `UPDATE`, `REPLACE` and `UPSERT` statements, both `OLD` and `NEW` can be used
to return the previous revision of a document together with the updated revision:
FOR u IN users
FILTER u.status == 'not active'
UPDATE u WITH { status: 'inactive' } IN users
RETURN { old: OLD, new: NEW }
!SUBSUBSECTION Calculations with OLD or NEW
It is also possible to run additional calculations with `LET` statements between the
data-modification part and the final `RETURN` of an AQL query. For example, the following
query performs an upsert operation and returns whether an existing document was
updated, or a new document was inserted. It does so by checking the `OLD` variable
after the `UPSERT` and using a `LET` statement to store a temporary string for
the operation type:
UPSERT { name: 'test' }
INSERT { name: 'test' }
UPDATE { } IN users
LET opType = IS_NULL(old) ? 'insert' : 'update'
RETURN { _key: NEW._key, type: opType }
!SUBSECTION Restrictions
The name of the modified collection (*users* and *backup* in the above cases)
must be known to the AQL executor at query-compile time and cannot change at
runtime. Using a bind parameter to specify the [collection name](../Glossary/README.md#collection-name) is allowed.
Data-modification queries are restricted to modifying data in a single
collection per query. That means a data-modification query cannot modify
data in multiple collections with a single query. It is still possible (and
was shown above) to read from one or many collections and modify data in another
within the same query.
Only a single data-modification operation can be used per AQL query. Data-modification
queries cannot be used inside subqueries. Data-modification operations can optionally
be followed by `LET` operations and a single `RETURN` operation to return data. If
expressions are used within these operations, they cannot contain subqueries or
access data in collections using AQL functions.
Finally, data-modification operations can optionally be followed by `LET` and `RETURN`,
but not by other statements such as `SORT`, `COLLECT` etc.
!SUBSECTION Transactional Execution
On a single server, data-modification operations are executed transactionally.
If a data-modification operation fails, any changes made by it will be rolled
back automatically as if they never happened.
In a cluster, AQL data-modification queries are currently not executed transactionally.
Additionally, *update*, *replace*, *upsert* and *remove* AQL queries currently
require the *_key* attribute to be specified for all documents that should be
modified or removed, even if a shared key attribute other than *_key* was chosen
for the collection. This restriction may be overcome in a future release of ArangoDB.