diff --git a/Documentation/Books/AQL/DataModification.mdpp b/Documentation/Books/AQL/DataModification.mdpp index 7f20782bbf..4d58f8c018 100644 --- a/Documentation/Books/AQL/DataModification.mdpp +++ b/Documentation/Books/AQL/DataModification.mdpp @@ -17,35 +17,64 @@ Let's start with the basics: `INSERT`, `UPDATE` and `REMOVE` operations on singl Here is an example that insert a document in an existing collection *users*: ```js -INSERT { firstName: "Anna", name: "Pavlova", profession: "artist" } IN 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. ```js -INSERT { _key: "GilbertoGil", firstName: "Gilberto", name: "Gil", city: "Fortalezza" } IN users +INSERT { + _key: "GilbertoGil", + firstName: "Gilberto", + name: "Gil", + city: "Fortalezza" +} IN users ``` -As Arango is schema-free, attributes of the documents may vary: +As ArangoDB is schema-free, attributes of the documents may vary: ```js -INSERT { _key: "PhilCarpenter", firstName: "Phil", name: "Carpenter", middleName: "G.", status: "inactive" } IN users +INSERT { + _key: "PhilCarpenter", + firstName: "Phil", + name: "Carpenter", + middleName: "G.", + status: "inactive" +} IN users ``` ```js -INSERT { _key: "NatachaDeclerck", firstName: "Natacha", name: "Declerck", location: "Antwerp" } 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 ```js -UPDATE "PhilCarpenter" WITH { status: "active", location: "Beijing" } IN users +UPDATE "PhilCarpenter" WITH { + status: "active", + location: "Beijing" +} IN users ``` Replace is an alternative to update where all attributes of the document are replaced. ```js -REPLACE { _key: "NatachaDeclerck", firstName: "Natacha", name: "Leclerc", status: "active", level: "premium" } IN users +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 : diff --git a/Documentation/Books/AQL/Functions/Array.mdpp b/Documentation/Books/AQL/Functions/Array.mdpp index 454c78de03..7bfe18578b 100644 --- a/Documentation/Books/AQL/Functions/Array.mdpp +++ b/Documentation/Books/AQL/Functions/Array.mdpp @@ -35,6 +35,10 @@ APPEND([ 1, 2, 3 ], [ 3, 4, 5, 2, 9 ], true) // [ 1, 2, 3, 4, 5, 9 ] ``` +!SUBSECTION COUNT() + +This is an alias for [LENGTH()](#length). + !SUBSECTION FIRST() `FIRST(anyArray) → firstElement` diff --git a/Documentation/Books/AQL/Functions/Document.mdpp b/Documentation/Books/AQL/Functions/Document.mdpp index dd36c11849..26f99da37e 100644 --- a/Documentation/Books/AQL/Functions/Document.mdpp +++ b/Documentation/Books/AQL/Functions/Document.mdpp @@ -6,25 +6,28 @@ additional language constructs. !SUBSECTION ATTRIBUTES() -`ATTRIBUTES(document, removeInternal, sort) → attributes` +`ATTRIBUTES(document, removeInternal, sort) → strArray` + +Return the attribute keys of the *document* as an array. Optionally omit +system 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 + The default is *false* and will return the attribute names in any order. +- returns **strArray** (array): the attribute keys of the input *document* as an array of strings ```js -ATTRIBUTES( {"foo": "bar", "_key": "123", "_custom": "yes" } ) +ATTRIBUTES( { "foo": "bar", "_key": "123", "_custom": "yes" } ) // [ "foo", "_key", "_custom" ] -ATTRIBUTES( {"foo": "bar", "_key": "123", "_custom": "yes" }, true ) +ATTRIBUTES( { "foo": "bar", "_key": "123", "_custom": "yes" }, true ) // [ "foo" ] -ATTRIBUTES( {"foo": "bar", "_key": "123", "_custom": "yes" }, false, true ) +ATTRIBUTES( { "foo": "bar", "_key": "123", "_custom": "yes" }, false, true ) // [ "_custom", "_key", "foo" ] ``` @@ -42,6 +45,10 @@ FOR attributeArray IN attributesPerDocument RETURN {attr, count} ``` +!SUBSECTION COUNT() + +This is an alias for [LENGTH()](#length). + !SUBSECTION HAS() `HAS(document, attributeName) → isPresent` diff --git a/Documentation/Books/AQL/Functions/Miscellaneous.mdpp b/Documentation/Books/AQL/Functions/Miscellaneous.mdpp index 07facd8339..db201cbe21 100644 --- a/Documentation/Books/AQL/Functions/Miscellaneous.mdpp +++ b/Documentation/Books/AQL/Functions/Miscellaneous.mdpp @@ -53,6 +53,10 @@ Return an array of collections. - returns **docArray** (array): each collection as a document with attributes *name* and *_id* in an array +!SUBSECTION COUNT() + +This is an alias for [LENGTH()](#length). + !SUBSECTION CURRENT_USER() `CURRENT_USER() → userName` @@ -196,14 +200,87 @@ CALL( "SUBSTRING", "this is a test", 0, 4 ) !SECTION Internal functions +The following functions are used during development of ArangoDB as a database +system, primarily for unit testing. They are not intended to be used by end +users, especially not in production environments. + !SUBSECTION FAIL() `FAIL(reason)` -!SUBSECTION NOOP() +Let a query fail on purpose. Can be used in a conditional branch, or to verify +if lazy evaluation / short circuiting is used for instance. -`NOOP(value) → retVal` +- **reason** (string): an error message +- returns nothing, because the query is aborted + +```js +RETURN 1 == 1 ? "okay" : FAIL("error") // "okay" +RETURN 1 == 1 || FAIL("error") ? true : false // true +RETURN 1 == 2 && FAIL("error") ? true : false // false +RETURN 1 == 1 && FAIL("error") ? true : false // aborted with error +``` + +!SUBSECTION NOOPT() + +`NOOPT(expression) → retVal` + +No-operation that prevents query compile-time optimizations. Constant expressions +can be forced to be evaluated at runtime with this. + +If there is a C++ implementation as well as a JavaScript implementation of an +AQL function, then it will enforce the use of the C++ version. + +- **expression** (any): arbitray expression +- returns **retVal** (any): the return value of the *expression* + +```js +// differences in execution plan (explain) +FOR i IN 1..3 RETURN (1 + 1) // const assignment +FOR i IN 1..3 RETURN NOOPT(1 + 1) // simple expression + +NOOPT( RAND() ) // C++ implementation +V8( RAND() ) // JavaScript implementation +``` + +!SUBSECTION PASSTHRU() + +`PASSTHRU(value) → retVal` + +This function is marked as non-deterministic so its argument withstands +query optimization. + +- **value** (any): a value of arbitrary type +- returns **retVal** (any): *value*, without optimizations + +!SUBSECTION SLEEP() + +`SLEEP(seconds) → null` + +Wait for a certain amount of time before continuing the query. + +- **seconds** (number): amount of time to wait +- returns a *null* value + +```js +SLEEP(1) // wait 1 second +SLEEP(0.02) // wait 20 milliseconds +``` !SUBSECTION V8() -`V8(value) → retVal` +`V8(expression) → retVal` + +No-operation that enforces the usage of the V8 JavaScript engine. If there is a +JavaScript implementation of an AQL function, for which there is also a C++ +implementation, the JavaScript version will be used. + +- **expression** (any): arbitray expression +- returns **retVal** (any): the return value of the *expression* + +```js +// differences in execution plan (explain) +FOR i IN 1..3 RETURN (1 + 1) // const assignment +FOR i IN 1..3 RETURN V8(1 + 1) // const assignment +FOR i IN 1..3 RETURN NOOPT(V8(1 + 1)) // v8 expression +``` diff --git a/Documentation/Books/AQL/Functions/Numeric.mdpp b/Documentation/Books/AQL/Functions/Numeric.mdpp index bf8c8d2878..e533f4b90d 100644 --- a/Documentation/Books/AQL/Functions/Numeric.mdpp +++ b/Documentation/Books/AQL/Functions/Numeric.mdpp @@ -390,6 +390,31 @@ Result: ] ``` +!SUBSECTION RANGE() + +`RANGE(start, stop, step) → numArray` + +Return an array of numbers in the specified range, optionally with increments +other than 1. + +For integer ranges, use the [range operator](../Operators.md#range-operator) +instead for better performance. + +- **start** (number): the value to start the range at (inclusive) +- **stop** (number): the value to end the range with (inclusive) +- **step** (number, *optional*): how much to increment in every step, + the default is *1.0* +- returns **numArray** (array): all numbers in the range as array + +```js +RANGE(1, 4) // [ 1, 2, 3, 4 ] +RANGE(1, 4, 2) // [ 1, 3 ] +RANGE(1, 4, 3) // [ 1, 4 ] +RANGE(1.5, 2.5) // [ 1.5, 2.5 ] +RANGE(1.5, 2.5, 0.5) // [ 1.5, 2, 2.5 ] +RANGE(-0.75, 1.1, 0.5) // [ -0.75, -0.25, 0.25, 0.75 ] +``` + !SUBSECTION ROUND() `ROUND(value) → roundedValue` diff --git a/Documentation/Books/AQL/Functions/String.mdpp b/Documentation/Books/AQL/Functions/String.mdpp index 93c57952ae..044a664699 100644 --- a/Documentation/Books/AQL/Functions/String.mdpp +++ b/Documentation/Books/AQL/Functions/String.mdpp @@ -92,6 +92,10 @@ CONTAINS("foobarbaz", "ba", true) // 3 CONTAINS("foobarbaz", "horse", true) // -1 ``` +!SUBSECTION COUNT() + +This is an alias for [LENGTH()](#length). + !SUBSECTION FIND_FIRST() `FIND_FIRST(text, search, start, end) → position` @@ -180,7 +184,7 @@ using wildcard matching. - **text** (string): the string to search in - **search** (string): a search pattern that can contain the wildcard characters - *%* (meaning any sequence of characters, including none) and *_* (any single + `%` (meaning any sequence of characters, including none) and `_` (any single character). Literal *%* and *:* must be escaped with two backslashes. *search* cannot be a variable or a document attribute. The actual value must be present at query parse time already. @@ -189,6 +193,19 @@ using wildcard matching. - returns **bool** (bool): *true* if the pattern is contained in *text*, and *false* otherwise +```js +LIKE("cart", "ca_t") // true +LIKE("carrot", "ca_t") // false +LIKE("carrot", "ca%t") // true + +LIKE("foo bar baz", "bar") // false +LIKE("foo bar baz", "%bar%") // true +LIKE("bar", "%bar%") // true + +LIKE("FoO bAr BaZ", "fOo%bAz") // false +LIKE("FoO bAr BaZ", "fOo%bAz", true) // true +``` + !SUBSECTION LOWER() `LOWER(value) → lowerCaseString` @@ -255,7 +272,7 @@ RANDOM_TOKEN(8) // "m9w50Ft9" `REGEX(text, search, caseInsensitive) → bool` Check whether the pattern *search* is contained in the string *text*, -using regular expression matching. +using regular expression matching. - **text** (string): the string to search in - **search** (string): a regular expression search pattern @@ -265,38 +282,46 @@ using regular expression matching. The regular expression may consist of literal characters and the following characters and sequences: -- *.*: the dot matches any single character except line terminators -- *\d*: matches a single digit, equivalent to [0-9] -- *\s*: matches a single whitespace character -- *\t*: matches a tab character -- *\r*: matches a carriage return -- *\n*: matches a line-feed character -- *[xyz]*: set of characters. matches any of the enclosed characters (i.e. +- `.` – the dot matches any single character except line terminators. + To include line terminators, use `[\s\S]` instead to simulate `.` with *DOTALL* flag. +- `\d` – matches a single digit, equivalent to `[0-9]` +- `\s` – matches a single whitespace character +- `\S` – matches a single non-whitespace character +- `\t` – matches a tab character +- `\r` – matches a carriage return +- `\n` – matches a line-feed character +- `[xyz]` – set of characters. matches any of the enclosed characters (i.e. *x*, *y* or *z* in this case -- *[^xyz]*: negated set of characters. matches any other character than the +- `[^xyz]` – negated set of characters. matches any other character than the enclosed ones (i.e. anything but *x*, *y* or *z* in this case) -- *[x-z]*: range of characters. matches any of the characters in the - specified range -- *[^x-z]*: negated range of characters. matches any other character than the +- `[x-z]` – range of characters. Matches any of the characters in the + specified range, e.g. `[0-9A-F]` to match any character in + *0123456789ABCDEF* +- `[^x-z]` – negated range of characters. Matches any other character than the ones specified in the range -- *(x|y)*: matches either *x* or *y* -- *^*: matches the beginning of the string -- *$*: matches the end of the string +- `(xyz)` – defines and matches a pattern group +- `(x|y)` – matches either *x* or *y* +- `^` – matches the beginning of the string (e.g. `^xyz`) +- `$` – matches the end of the string (e.g. `xyz$`) -Note that the characters *.*, \*, *?*, *[*, *]*, *(*, *)*, *{*, *}*, *^*, -and *$* have a special meaning in regular expressions and may need to be -escaped using a backslash (*\\*). A literal backslash should also be escaped -using another backslash, i.e. *\\\\*. +Note that the characters `.`, `*`, `?`, `[`, `]`, `(`, `)`, `{`, `}`, `^`, +and `$` have a special meaning in regular expressions and may need to be +escaped using a backslash (`\\`). A literal backslash should also be escaped +using another backslash, i.e. `\\\\`. Characters and sequences may optionally be repeated using the following quantifiers: -- *x\**: matches zero or more occurrences of *x* -- *x+*: matches one or more occurrences of *x* -- *x?*: matches one or zero occurrences of *x* -- *x{y}*: matches exactly *y* occurrences of *x* -- *x{y,z}*: matches between *y* and *z* occurrences of *x* -- *x{y,}*: matches at least *y* occurences of *x* +- `x*` – matches zero or more occurrences of *x* +- `x+` – matches one or more occurrences of *x* +- `x?` – matches one or zero occurrences of *x* +- `x{y}` – matches exactly *y* occurrences of *x* +- `x{y,z}` – matches between *y* and *z* occurrences of *x* +- `x{y,}` – matches at least *y* occurences of *x* + +Note that `xyz+` matches *xyzzz*, but if you want to match *xyzxyz* instead, +you need to define a pattern group by wrapping the subexpression in parentheses +and place the quantifier right behind it: `(xyz)+`. If the regular expression in *search* is invalid, a warning will be raised and the function will return *false*. diff --git a/Documentation/Books/AQL/Functions/TypeCast.mdpp b/Documentation/Books/AQL/Functions/TypeCast.mdpp index 52119a60a1..9d4a16ffae 100644 --- a/Documentation/Books/AQL/Functions/TypeCast.mdpp +++ b/Documentation/Books/AQL/Functions/TypeCast.mdpp @@ -161,8 +161,8 @@ The following type check functions are available: - `IS_DOCUMENT(value) → bool`: This is an alias for *IS_OBJECT()* - `IS_DATESTRING(value) → bool`: Check whether *value* is a string that can be used - in a date function. This includes partial dates such as *2015* or *2015-10* and - strings containing invalid dates such as *2015-02-31*. The function will return + in a date function. This includes partial dates such as *"2015"* or *"2015-10"* and + strings containing invalid dates such as *"2015-02-31"*. The function will return false for all non-string values, even if some of them may be usable in date functions. - `TYPENAME(value) → typeName`: Return the data type name of *value*. The data type diff --git a/Documentation/Books/AQL/Operators.mdpp b/Documentation/Books/AQL/Operators.mdpp index 905c760b6e..940268d3f6 100644 --- a/Documentation/Books/AQL/Operators.mdpp +++ b/Documentation/Books/AQL/Operators.mdpp @@ -59,7 +59,7 @@ or underscore. ``` "abc" LIKE "a%" // true "abc" LIKE "_bc" // true -"a_b_foo" LIKE "a\\_b\\_f%" // true +"a_b_foo" LIKE "a\\_b\\_foo" // true ``` The pattern matching performed by the *LIKE* operator is case-sensitive. @@ -182,7 +182,14 @@ AQL supports the following arithmetic operators: - */* division - *%* modulus -The unary plus and unary minus are supported as well. +Unary plus and unary minus are supported as well: + +```js +LET x = -5 +LET y = 1 +RETURN [-x, +y] +// [5, 1] +``` For exponentiation, there is a [numeric function](Functions/Numeric.md#pow) *POW()*. @@ -202,7 +209,7 @@ Some example arithmetic operations: The arithmetic operators accept operands of any type. Passing non-numeric values to an arithmetic operator will cast the operands to numbers using the type casting rules -applied by the `TO_NUMBER` function: +applied by the [TO_NUMBER()](Functions/TypeCast.md#tonumber) function: - `null` will be converted to `0` - `false` will be converted to `0`, true will be converted to `1` @@ -215,8 +222,8 @@ applied by the `TO_NUMBER` function: `0`. - objects / documents are converted to the number `0`. -An arithmetic operation that produces an invalid value, such as `1 / 0` will also produce -a result value of `0`. +An arithmetic operation that produces an invalid value, such as `1 / 0` (division by zero) +will also produce a result value of `0`. Here are a few examples: