mirror of https://gitee.com/bigwinds/arangodb
424 lines
14 KiB
Plaintext
424 lines
14 KiB
Plaintext
!CHAPTER Document functions
|
|
|
|
AQL provides below listed functions to operate on objects / document values.
|
|
Also see [object access](../Fundamentals/DataTypes.md#objects-documents) for
|
|
additional language constructs.
|
|
|
|
!SUBSECTION ATTRIBUTES()
|
|
|
|
`ATTRIBUTES(document, removeInternal, sort) → attributes`
|
|
|
|
- **document** (object): an arbitrary document / object
|
|
- **removeInternal** (bool, *optional*): whether all system attributes (*_key*, *_id* etc.,
|
|
every attribute key that starts with an underscore) shall be omitted in the result.
|
|
The default is *false*.
|
|
- **sort** (bool, *optional*): optionally sort the resulting array alphabetically.
|
|
The default is *false* and will return the attribute names in a random order.
|
|
- returns **attributes** (array): the attribute keys of the input **document** as an
|
|
array of strings
|
|
|
|
```js
|
|
ATTRIBUTES( {"foo": "bar", "_key": "123", "_custom": "yes" } )
|
|
// [ "foo", "_key", "_custom" ]
|
|
|
|
ATTRIBUTES( {"foo": "bar", "_key": "123", "_custom": "yes" }, true )
|
|
// [ "foo" ]
|
|
|
|
ATTRIBUTES( {"foo": "bar", "_key": "123", "_custom": "yes" }, false, true )
|
|
// [ "_custom", "_key", "foo" ]
|
|
```
|
|
|
|
Complex example to count how often every attribute key occurs in the documents
|
|
of *collection* (expensive on large collections):
|
|
|
|
```js
|
|
LET attributesPerDocument = (
|
|
FOR doc IN collection RETURN ATTRIBUTES(doc, true)
|
|
)
|
|
FOR attributeArray IN attributesPerDocument
|
|
FOR attribute IN attributeArray
|
|
COLLECT attr = attribute WITH COUNT INTO count
|
|
SORT count DESC
|
|
RETURN {attr, count}
|
|
```
|
|
|
|
!SUBSECTION HAS()
|
|
|
|
`HAS(document, attributeName) → isPresent`
|
|
|
|
Test whether an attribute is present in the provided document.
|
|
|
|
- **document** (object): an arbitrary document / object
|
|
- **attributeName** (string): the attribute key to test for
|
|
- returns **isPresent** (bool): *true* if *document* has an attribute named
|
|
*attributeName*, and *false* otherwise. An attribute with a falsy value (*0*, *false*,
|
|
empty string *""*) or *null* is also considered as present and returns *true*.
|
|
|
|
```js
|
|
HAS( { name: "Jane" }, "name" ) // true
|
|
HAS( { name: "Jane" }, "age" ) // false
|
|
HAS( { name: null }, "name" ) // true
|
|
```
|
|
|
|
Note that the function checks if the specified attribute exists. This is different
|
|
from similar ways to test for the existance of an attribute, in case the attribute
|
|
has a falsy value or is not present (implicitly *null* on object access):
|
|
|
|
```js
|
|
!!{ name: "" }.name // false
|
|
HAS( { name: "" }, "name") // true
|
|
|
|
{ name: null }.name == null // true
|
|
{ }.name == null // true
|
|
HAS( { name: null }, "name" ) // true
|
|
HAS( { }, "name" ) // false
|
|
```
|
|
|
|
!SUBSECTION IS_SAME_COLLECTION()
|
|
|
|
`IS_SAME_COLLECTION(collectionName, documentHandle) → bool`
|
|
|
|
collection id as the collection specified in *collection*. *document* can either be
|
|
a [document handle](../../Manual/Appendix/Glossary.html#document-handle) string, or a document with
|
|
an *_id* attribute. The function does not validate whether the collection actually
|
|
contains the specified document, but only compares the name of the specified collection
|
|
with the collection name part of the specified document.
|
|
If *document* is neither an object with an *id* attribute nor a *string* value,
|
|
the function will return *null* and raise a warning.
|
|
|
|
- **collectionName** (string): the name of a collection as string
|
|
- **documentHandle** (string|object): a document identifier string (e.g. *_users/1234*)
|
|
or a regular document from a collection. Passing either a non-string or a non-document
|
|
or a document without an *_id* attribute will result in an error.
|
|
- returns **bool** (bool): return *true* if the collection of *documentHandle* is the same
|
|
as *collectionName*, otherwise *false*
|
|
|
|
```js
|
|
// true
|
|
IS_SAME_COLLECTION( "_users", "_users/my-user" )
|
|
IS_SAME_COLLECTION( "_users", { _id: "_users/my-user" } )
|
|
|
|
// false
|
|
IS_SAME_COLLECTION( "_users", "foobar/baz")
|
|
IS_SAME_COLLECTION( "_users", { _id: "something/else" } )
|
|
```
|
|
|
|
!SUBSECTION KEEP()
|
|
|
|
`KEEP(document, attributeName1, attributeName2, ... attributeNameN) → doc`
|
|
|
|
Keep only the attributes *attributeName* to *attributeNameN* of *document*.
|
|
All other attributes will be removed from the result.
|
|
|
|
- **document** (object): a document / object
|
|
- **attributeNames** (string, *repeatable*): an arbitrary number of attribute
|
|
names as multiple arguments
|
|
- returns **doc** (object): a document with only the specified attributes on
|
|
the top-level
|
|
|
|
```js
|
|
KEEP(doc, "firstname", "name", "likes")
|
|
```
|
|
|
|
`KEEP(document, attributeNameArray) → doc`
|
|
|
|
- **document** (object): a document / object
|
|
- **attributeNameArray** (array): an array of attribute names as strings
|
|
- returns **doc** (object): a document with only the specified attributes on
|
|
the top-level
|
|
|
|
```js
|
|
KEEP(doc, [ "firstname", "name", "likes" ])
|
|
```
|
|
|
|
!SUBSECTION LENGTH()
|
|
|
|
`LENGTH(doc) → attrCount`
|
|
|
|
Determine the [number of elements](Array.md#length) in an array,
|
|
the number of attribute keys of an object / document,
|
|
the [amount of documents](Miscellaneous.md#length) in a collection,
|
|
or the [character length](String.md#length) of a string.
|
|
|
|
- **doc** (object): a document / object
|
|
- returns **attrCount** (number): the number of attribute keys in *doc*, regardless
|
|
of their values
|
|
|
|
!SUBSECTION MATCHES()
|
|
|
|
`MATCHES(document, examples, returnIndex) → match`
|
|
|
|
Compare the given *document* against each example document provided. The comparisons
|
|
will be started with the first example. All attributes of the example will be compared
|
|
against the attributes of *document*. If all attributes match, the comparison stops
|
|
and the result is returned. If there is a mismatch, the function will continue the
|
|
comparison with the next example until there are no more examples left.
|
|
|
|
The *examples* can be an array of 1..n example documents or a single document,
|
|
with any number of attributes each.
|
|
|
|
- **document** (object): document to determine whether it matches any example
|
|
- **examples** (object|array): a single document, or an array of documents to compare
|
|
against. Specifying an empty array is not allowed.
|
|
- **returnIndex** (bool): by setting this flag to *true*, the index of the example that
|
|
matched will be returned (starting at offset 0), or *-1* if there was no match.
|
|
The default is **false** and makes the function return a boolean.
|
|
- returns **match** (bool|number): if *document* matches one of the examples, *true* is
|
|
returned, otherwise *false*. A number is returned instead if *returnIndex* is used.
|
|
|
|
```js
|
|
LET doc = {
|
|
name: "jane",
|
|
age: 27,
|
|
active: true
|
|
}
|
|
RETURN MATCHES(doc, { age: 27, active: true } )
|
|
```
|
|
|
|
This will return **true**, because all attributes of the example are present in the document.
|
|
|
|
```js
|
|
RETURN MATCHES(
|
|
{ "test": 1 },
|
|
[
|
|
{ "test": 1, "foo": "bar" },
|
|
{ "foo": 1 },
|
|
{ "test": 1 }
|
|
], true)
|
|
```
|
|
|
|
This will return *2*, because the third example matches, and because the
|
|
*returnIndex* flag is set to *true*.
|
|
|
|
!SUBSECTION MERGE()
|
|
|
|
`MERGE(document1, document2, ... documentN) → mergedDocument`
|
|
|
|
Merge the documents *document1* to *documentN* into a single document.
|
|
If document attribute keys are ambiguous, the merged result will contain the values
|
|
of the documents contained later in the argument list.
|
|
|
|
Note that merging will only be done for top-level attributes. If you wish to
|
|
merge sub-attributes, use [MERGE_RECURSIVE()](#mergerecursive) instead.
|
|
|
|
- **documents** (object, *repeatable*): an arbitrary number of documents as
|
|
multiple arguments, at least 2
|
|
- returns **mergedDocument** (object): a combined document
|
|
|
|
For example, two documents with distinct attribute names can easily be merged into one:
|
|
|
|
```js
|
|
MERGE(
|
|
{ "user1": { "name": "Jane" } },
|
|
{ "user2": { "name": "Tom" } }
|
|
)
|
|
// { "user1": { "name": "Jane" }, "user2": { "name": "Tom" } }
|
|
```
|
|
|
|
When merging documents with identical attribute names, the attribute values of the
|
|
latter documents will be used in the end result:
|
|
|
|
```js
|
|
MERGE(
|
|
{ "users": { "name": "Jane" } },
|
|
{ "users": { "name": "Tom" } }
|
|
)
|
|
// { "users": { "name": "Tom" } }
|
|
```
|
|
|
|
`MERGE(docArray) → mergedDocument`
|
|
|
|
*MERGE* works with a single array parameter, too. This variant allows combining the
|
|
attributes of multiple objects in an array into a single object.
|
|
|
|
- **docArray** (array): an array of documents, as sole argument
|
|
- returns **mergedDocument** (object): a combined document
|
|
|
|
```js
|
|
MERGE(
|
|
[
|
|
{ foo: "bar" },
|
|
{ quux: "quetzalcoatl", ruled: true },
|
|
{ bar: "baz", foo: "done" }
|
|
]
|
|
)
|
|
```
|
|
|
|
This will now return:
|
|
|
|
```js
|
|
{
|
|
"foo": "done",
|
|
"quux": "quetzalcoatl",
|
|
"ruled": true,
|
|
"bar": "baz"
|
|
}
|
|
```
|
|
|
|
!SUBSECTION MERGE_RECURSIVE()
|
|
|
|
`MERGE_RECURSIVE(document1, document2, ... documentN) → mergedDocument`
|
|
|
|
Recursively merge the documents *document1* to *documentN* into a single document.
|
|
If document attribute keys are ambiguous, the merged result will contain the values
|
|
of the documents contained later in the argument list.
|
|
|
|
- **documents** (object, *repeatable*): an arbitrary number of documents as
|
|
multiple arguments, at least 2
|
|
- returns **mergedDocument** (object): a combined document
|
|
|
|
For example, two documents with distinct attribute names can easily be merged into one:
|
|
|
|
```js
|
|
MERGE_RECURSIVE(
|
|
{ "user-1": { "name": "Jane", "livesIn": { "city": "LA" } } },
|
|
{ "user-1": { "age": 42, "livesIn": { "state": "CA" } } }
|
|
)
|
|
// { "user-1": { "name": "Jane", "livesIn": { "city": "LA", "state": "CA" }, "age": 42 } }
|
|
```
|
|
|
|
*MERGE_RECURSIVE()* does not support the single array parameter variant that *MERGE* offers.
|
|
|
|
!SUBSECTION PARSE_IDENTIFIER()
|
|
|
|
`PARSE_IDENTIFIER(documentHandle) → parts`
|
|
|
|
Parse a [document handle](../../Manual/Appendix/Glossary.html#document-handle) and return its
|
|
individual parts a separate attributes.
|
|
|
|
This function can be used to easily determine the
|
|
[collection name](../../Manual/Appendix/Glossary.html#collection-name) and key of a given document.
|
|
|
|
- **documentHandle** (string|object): a document identifier string (e.g. *_users/1234*)
|
|
or a regular document from a collection. Passing either a non-string or a non-document
|
|
or a document without an *_id* attribute will result in an error.
|
|
- returns **parts** (object): an object with the attributes *collection* and *key*
|
|
|
|
```js
|
|
PARSE_IDENTIFIER("_users/my-user")
|
|
// { "collection": "_users", "key": "my-user" }
|
|
|
|
PARSE_IDENTIFIER( { "_id": "mycollection/mykey", "value": "some value" } )
|
|
// { "collection": "mycollection", "key": "mykey" }
|
|
```
|
|
|
|
!SUBSECTION TRANSLATE()
|
|
|
|
`TRANSLATE(value, lookupDocument, defaultValue) → mappedValue`
|
|
|
|
Look up the specified *value* in the *lookupDocument*. If *value* is a key in
|
|
*lookupDocument*, then *value* will be replaced with the lookup value found.
|
|
If *value* is not present in *lookupDocument*, then *defaultValue* will be returned
|
|
if specified. If no *defaultValue* is specified, *value* will be returned unchanged.
|
|
|
|
- **value** (string): the value to encode according to the mapping
|
|
- **lookupDocument** (object): a key/value mapping as document
|
|
- **defaultValue** (any, *optional*): a fallback value in case *value* is not found
|
|
- returns **mappedValue** (any): the encoded value, or the unaltered *value* or *defaultValue*
|
|
(if supplied) in case it couldn't be mapped
|
|
|
|
```js
|
|
TRANSLATE("FR", { US: "United States", UK: "United Kingdom", FR: "France" } )
|
|
// "France"
|
|
|
|
TRANSLATE(42, { foo: "bar", bar: "baz" } )
|
|
// 42
|
|
|
|
TRANSLATE(42, { foo: "bar", bar: "baz" }, "not found!")
|
|
// "not found!"
|
|
```
|
|
|
|
!SUBSECTION UNSET()
|
|
|
|
`UNSET(document, attributeName1, attributeName2, ... attributeNameN) → doc`
|
|
|
|
Remove the attributes *attributeName1* to *attributeNameN* from *document*.
|
|
All other attributes will be preserved.
|
|
|
|
- **document** (object): a document / object
|
|
- **attributeNames** (string, *repeatable*): an arbitrary number of attribute
|
|
names as multiple arguments, at least 1
|
|
- returns **doc** (object): *document* without the specified attributes on the
|
|
top-level
|
|
|
|
```js
|
|
UNSET( doc, "_id", "_key", "foo", "bar" )
|
|
```
|
|
|
|
`UNSET(document, attributeNameArray) → doc`
|
|
|
|
- **document** (object): a document / object
|
|
- **attributeNameArray** (array): an array of attribute names as strings
|
|
- returns **doc** (object): *document* without the specified attributes on the
|
|
top-level
|
|
|
|
```js
|
|
UNSET( doc, [ "_id", "_key", "foo", "bar" ] )
|
|
```
|
|
|
|
!SUBSECTION UNSET_RECURSIVE()
|
|
|
|
`UNSET_RECURSIVE(document, attributeName1, attributeName2, ... attributeNameN) → doc`
|
|
|
|
Recursively remove the attributes *attributeName1* to *attributeNameN* from
|
|
*document* and its sub-documents. All other attributes will be preserved.
|
|
|
|
- **document** (object): a document / object
|
|
- **attributeNames** (string, *repeatable*): an arbitrary number of attribute
|
|
names as multiple arguments, at least 1
|
|
- returns **doc** (object): *document* without the specified attributes on
|
|
all levels (top-level as well as nested objects)
|
|
|
|
```js
|
|
UNSET_RECURSIVE( doc, "_id", "_key", "foo", "bar" )
|
|
```
|
|
|
|
`UNSET_RECURSIVE(document, attributeNameArray) → doc`
|
|
|
|
- **document** (object): a document / object
|
|
- **attributeNameArray** (array): an array of attribute names as strings
|
|
- returns **doc** (object): *document* without the specified attributes on
|
|
all levels (top-level as well as nested objects)
|
|
|
|
```js
|
|
UNSET_RECURSIVE( doc, [ "_id", "_key", "foo", "bar" ] )
|
|
```
|
|
|
|
!SUBSECTION VALUES()
|
|
|
|
`VALUES(document, removeInternal) → anyArray`
|
|
|
|
Return the attribute values of the *document* as an array. Optionally omit
|
|
system attributes.
|
|
|
|
- **document** (object): a document / object
|
|
- **removeInternal** (bool, *optional*): if set to *true*, then all internal attributes
|
|
(such as *_id*, *_key* etc.) are removed from the result
|
|
- returns **anyArray** (array): the values of *document* returned in any order
|
|
|
|
```js
|
|
VALUES( { "_key": "users/jane", "name": "Jane", "age": 35 } )
|
|
// [ "Jane", 35, "users/jane" ]
|
|
|
|
VALUES( { "_key": "users/jane", "name": "Jane", "age": 35 }, true )
|
|
// [ "Jane", 35 ]
|
|
```
|
|
|
|
!SUBSECTION ZIP()
|
|
|
|
`ZIP(keys, values) → doc`
|
|
|
|
Return a document object assembled from the separate parameters *keys* and *values*.
|
|
|
|
*keys* and *values* must be arrays and have the same length.
|
|
|
|
- **keys** (array): an array of strings, to be used as attribute names in the result
|
|
- **values** (array): an array with elements of arbitrary types, to be used as
|
|
attribute values
|
|
- returns **doc** (object): a document with the keys and values assembled
|
|
|
|
```js
|
|
ZIP( [ "name", "active", "hobbies" ], [ "some user", true, [ "swimming", "riding" ] ] )
|
|
// { "name": "some user", "active": true, "hobbies": [ "swimming", "riding" ] }
|
|
```
|