diff --git a/Documentation/Books/Users/Aql/Advanced.mdpp b/Documentation/Books/Users/Aql/Advanced.mdpp index cfb0c9c3de..7229f1026e 100644 --- a/Documentation/Books/Users/Aql/Advanced.mdpp +++ b/Documentation/Books/Users/Aql/Advanced.mdpp @@ -1,216 +1,6 @@ !CHAPTER Advanced features -!SUBSECTION Subqueries -Wherever an expression is allowed in AQL, a subquery can be placed. A subquery -is a query part that can introduce its own local variables without affecting -variables and values in its outer scope(s). +* [Combining queries](CombiningQueries.md) +* [Array operators](ArrayOperators.md) -It is required that subqueries be put inside parentheses *(* and *)* to -explicitly mark their start and end points: - -```js -FOR p IN persons - LET recommendations = ( - FOR r IN recommendations - FILTER p.id == r.personId - SORT p.rank DESC - LIMIT 10 - RETURN r - ) - RETURN { person : p, recommendations : recommendations } -``` - -```js -FOR p IN persons - COLLECT city = p.city INTO g - RETURN { - city : city, - numPersons : LENGTH(g), - maxRating: MAX( - FOR r IN g - RETURN r.p.rating - )} -``` - -Subqueries may also include other subqueries. - -!SUBSECTION Array expansion - -In order to access a named attribute from all elements in an array easily, AQL -offers the shortcut operator [\*] for array variable expansion. - -Using the [\*] operator with an array variable will iterate over all elements -in the array, thus allowing to access a particular attribute of each element. It is -required that the expanded variable is an array. The result of the [\*] -operator is again an array. - -To demonstrate the array expansion operator, let's go on with the following three -example *users* documents: - -```json -[ - { - name: "john", - age: 35, - friends: [ - { name: "tina", age: 43 }, - { name: "helga", age: 52 }, - { name: "alfred", age: 34 } - ] - }, - { - name: "yves", - age: 24, - friends: [ - { name: "sergei", age: 27 }, - { name: "tiffany", age: 25 } - ] - }, - { - name: "sandra", - age: 40, - friends: [ - { name: "bob", age: 32 }, - { name: "elena", age: 48 } - ] - } -] -``` - -With the [\*] operator it becomes easy to query just the names of the -friends for each user: - -``` -FOR u IN users - RETURN { name: u.name, friends: u.friends[*].name } -``` - -This will produce: - -```json -[ - { "name" : "john", "friends" : [ "tina", "helga", "alfred" ] }, - { "name" : "yves", "friends" : [ "sergei", "tiffany" ] }, - { "name" : "sandra", "friends" : [ "bob", "elena" ] } -] -``` - -This a shortcut for the longer, semantically equivalent query: - -``` -FOR u IN users - RETURN { name: u.name, friends: (FOR f IN u.friends RETURN f.name) } -``` - -While producing a result with the [\*] operator, it is also possible -to filter while iterating over the array, and to create a projection using the -current array element. - -For example, to return only the names of friends that have an *age* value -higher than the user herself an inline *FILTER* can be used: - -``` -FOR u IN users - RETURN { name: u.name, friends: u.friends[* FILTER CURRENT.age > u.age].name } -``` - -The pseudo-variable *CURRENT* can be used to access the current array element. -The *FILTER* condition can refer to *CURRENT* or any variables valid in the -outer scope. - -To return a projection of the current element, use *RETURN*. If a *FILTER* is -also present, *RETURN* must come later. - -``` -FOR u IN users - RETURN u.friends[* RETURN CONCAT(CURRENT.name, " is a friend of ", u.name)] -``` - -The above will return: - -```json -[ - [ - "tina is a friend of john", - "helga is a friend of john", - "alfred is a friend of john" - ], - [ - "sergei is a friend of yves", - "tiffany is a friend of yves" - ], - [ - "bob is a friend of sandra", - "elena is a friend of sandra" - ] -] -``` - -!SUBSECTION Array contraction - -In order to collapse (or flatten) results in nested arrays, AQL provides the [\*\*] -operator. It works similar to the [\*] operator, but additionally collapses nested -arrays. How many levels are collapsed is determined by the amount of \* characters used. - -For example, the following query produces an array of friend names per user: - -``` -FOR u IN users - RETURN u.friends[*].name -``` - -As we have multiple users, the overall result is a nested array: - -```json -[ - [ - "tina", - "helga", - "alfred" - ], - [ - "sergei", - "tiffany" - ], - [ - "bob", - "elena" - ] -] -``` - -If the goal is to get rid of the nested array, we can apply the [\*\*] operator on the -result. Simplying appending [\*\*] to the query won't help, because *u.friends* -is not a nested (multi-dimensional) array, but a simple (one-dimensional) array. Still, -the [\*\*] can be used if it has access to a multi-dimensional nested result. - -We can easily create a nested result like this: - -``` -RETURN ( - FOR u IN users RETURN u.friends[*].name -) -``` - -By now appending the [\*\*] operator the end of the query, the query result becomes: - -``` -RETURN ( - FOR u IN users RETURN u.friends[*].name -)[**] -``` - -```json -[ - [ - "tina", - "helga", - "alfred", - "sergei", - "tiffany", - "bob", - "elena" - ] -] -``` diff --git a/Documentation/Books/Users/Aql/ArrayFunctions.mdpp b/Documentation/Books/Users/Aql/ArrayFunctions.mdpp index d13f898d29..6a34fb742d 100644 --- a/Documentation/Books/Users/Aql/ArrayFunctions.mdpp +++ b/Documentation/Books/Users/Aql/ArrayFunctions.mdpp @@ -254,5 +254,7 @@ AQL supports the following functions to operate on array values: /* [ "a", "b", "c", "e" ] */ REMOVE_NTH([ "a", "b", "c", "d", "e" ], -2) -Apart from these functions, AQL also offers several language constructs (e.g. -[FOR](../AqlOperations/For.md), [SORT](../AqlOperations/Sort.md), [LIMIT](../AqlOperations/Limit.md), [COLLECT](../AqlOperations/Collect.md)) to operate on arrays. + +Apart from these functions, AQL also offers several language constructs: +- [array operators](ArrayOperators.md) for array expansion and contraction, +- operations for array manipulations like [FOR](../AqlOperations/For.md), [SORT](../AqlOperations/Sort.md), [LIMIT](../AqlOperations/Limit.md), [COLLECT](../AqlOperations/Collect.md). diff --git a/Documentation/Books/Users/Aql/ArrayOperators.mdpp b/Documentation/Books/Users/Aql/ArrayOperators.mdpp new file mode 100644 index 0000000000..ff727326b0 --- /dev/null +++ b/Documentation/Books/Users/Aql/ArrayOperators.mdpp @@ -0,0 +1,182 @@ +!CHAPTER Array Operators + + +!SUBSECTION Array expansion + +In order to access a named attribute from all elements in an array easily, AQL +offers the shortcut operator [\*] for array variable expansion. + +Using the [\*] operator with an array variable will iterate over all elements +in the array, thus allowing to access a particular attribute of each element. It is +required that the expanded variable is an array. The result of the [\*] +operator is again an array. + +To demonstrate the array expansion operator, let's go on with the following three +example *users* documents: + +```json +[ + { + name: "john", + age: 35, + friends: [ + { name: "tina", age: 43 }, + { name: "helga", age: 52 }, + { name: "alfred", age: 34 } + ] + }, + { + name: "yves", + age: 24, + friends: [ + { name: "sergei", age: 27 }, + { name: "tiffany", age: 25 } + ] + }, + { + name: "sandra", + age: 40, + friends: [ + { name: "bob", age: 32 }, + { name: "elena", age: 48 } + ] + } +] +``` + +With the [\*] operator it becomes easy to query just the names of the +friends for each user: + +``` +FOR u IN users + RETURN { name: u.name, friends: u.friends[*].name } +``` + +This will produce: + +```json +[ + { "name" : "john", "friends" : [ "tina", "helga", "alfred" ] }, + { "name" : "yves", "friends" : [ "sergei", "tiffany" ] }, + { "name" : "sandra", "friends" : [ "bob", "elena" ] } +] +``` + +This a shortcut for the longer, semantically equivalent query: + +``` +FOR u IN users + RETURN { name: u.name, friends: (FOR f IN u.friends RETURN f.name) } +``` + +While producing a result with the [\*] operator, it is also possible +to filter while iterating over the array, and to create a projection using the +current array element. + +For example, to return only the names of friends that have an *age* value +higher than the user herself an inline *FILTER* can be used: + +``` +FOR u IN users + RETURN { name: u.name, friends: u.friends[* FILTER CURRENT.age > u.age].name } +``` + +The pseudo-variable *CURRENT* can be used to access the current array element. +The *FILTER* condition can refer to *CURRENT* or any variables valid in the +outer scope. + +To return a projection of the current element, use *RETURN*. If a *FILTER* is +also present, *RETURN* must come later. + +``` +FOR u IN users + RETURN u.friends[* RETURN CONCAT(CURRENT.name, " is a friend of ", u.name)] +``` + +The above will return: + +```json +[ + [ + "tina is a friend of john", + "helga is a friend of john", + "alfred is a friend of john" + ], + [ + "sergei is a friend of yves", + "tiffany is a friend of yves" + ], + [ + "bob is a friend of sandra", + "elena is a friend of sandra" + ] +] +``` + +!SUBSECTION Array contraction + +In order to collapse (or flatten) results in nested arrays, AQL provides the [\*\*] +operator. It works similar to the [\*] operator, but additionally collapses nested +arrays. How many levels are collapsed is determined by the amount of \* characters used. + +For example, the following query produces an array of friend names per user: + +``` +FOR u IN users + RETURN u.friends[*].name +``` + +As we have multiple users, the overall result is a nested array: + +```json +[ + [ + "tina", + "helga", + "alfred" + ], + [ + "sergei", + "tiffany" + ], + [ + "bob", + "elena" + ] +] +``` + +If the goal is to get rid of the nested array, we can apply the [\*\*] operator on the +result. Simplying appending [\*\*] to the query won't help, because *u.friends* +is not a nested (multi-dimensional) array, but a simple (one-dimensional) array. Still, +the [\*\*] can be used if it has access to a multi-dimensional nested result. + +We can easily create a nested result like this: + +``` +RETURN ( + FOR u IN users RETURN u.friends[*].name +) +``` + +By now appending the [\*\*] operator the end of the query, the query result becomes: + +``` +RETURN ( + FOR u IN users RETURN u.friends[*].name +)[**] +``` + +```json +[ + [ + "tina", + "helga", + "alfred", + "sergei", + "tiffany", + "bob", + "elena" + ] +] +``` diff --git a/Documentation/Books/Users/Aql/CombiningQueries.mdpp b/Documentation/Books/Users/Aql/CombiningQueries.mdpp new file mode 100644 index 0000000000..3526025036 --- /dev/null +++ b/Documentation/Books/Users/Aql/CombiningQueries.mdpp @@ -0,0 +1,38 @@ +!CHAPTER Combining queries + +!SUBSECTION Subqueries + +Wherever an expression is allowed in AQL, a subquery can be placed. A subquery +is a query part that can introduce its own local variables without affecting +variables and values in its outer scope(s). + +It is required that subqueries be put inside parentheses *(* and *)* to +explicitly mark their start and end points: + +```js +FOR p IN persons + LET recommendations = ( + FOR r IN recommendations + FILTER p.id == r.personId + SORT p.rank DESC + LIMIT 10 + RETURN r + ) + RETURN { person : p, recommendations : recommendations } +``` + +```js +FOR p IN persons + COLLECT city = p.city INTO g + RETURN { + city : city, + numPersons : LENGTH(g), + maxRating: MAX( + FOR r IN g + RETURN r.p.rating + )} +``` + +Subqueries may also include other subqueries. + + diff --git a/Documentation/Books/Users/Aql/Operators.mdpp b/Documentation/Books/Users/Aql/Operators.mdpp index e469c72d37..c4a744efca 100644 --- a/Documentation/Books/Users/Aql/Operators.mdpp +++ b/Documentation/Books/Users/Aql/Operators.mdpp @@ -201,6 +201,12 @@ will produce the following result: [ 2010, 2011, 2012, 2013 ] + +!SUBSUBSECTION Array operators + +AQL provides [array operators](ArrayOperators.md) [\*] for array variable expansion and [\*\*] for array contraction. + + !SUBSUBSECTION Operator precedence The operator precedence in AQL is similar as in other familiar languages (lowest precedence first): diff --git a/Documentation/Books/Users/SUMMARY.md b/Documentation/Books/Users/SUMMARY.md index b804b4302a..d70d24f111 100644 --- a/Documentation/Books/Users/SUMMARY.md +++ b/Documentation/Books/Users/SUMMARY.md @@ -103,6 +103,8 @@ * [Named Operations](Aql/GraphOperations.md) * [Other](Aql/GraphFunctions.md) * [Advanced Features](Aql/Advanced.md) + * [Combining Queries](Aql/CombiningQueries.md) + * [Array Operators](Aql/ArrayOperators.md) * [Extending AQL](AqlExtending/README.md) * [Conventions](AqlExtending/Conventions.md) * [Registering Functions](AqlExtending/Functions.md)