mirror of https://gitee.com/bigwinds/arangodb
Documentation: links between array related features
This commit is contained in:
parent
583bc90626
commit
11a6176ffa
|
@ -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 <i>[\*]</i> for array variable expansion.
|
||||
|
||||
Using the <i>[\*]</i> 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 <i>[\*]</i>
|
||||
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 <i>[\*]</i> 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 <i>[\*]</i> 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 <i>[\*\*]</i>
|
||||
operator. It works similar to the <i>[\*]</i> operator, but additionally collapses nested
|
||||
arrays. How many levels are collapsed is determined by the amount of <i>\*</i> 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 <i>[\*\*]</i> operator on the
|
||||
result. Simplying appending <i>[\*\*]</i> to the query won't help, because *u.friends*
|
||||
is not a nested (multi-dimensional) array, but a simple (one-dimensional) array. Still,
|
||||
the <i>[\*\*]</i> 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 <i>[\*\*]</i> 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"
|
||||
]
|
||||
]
|
||||
```
|
||||
|
|
|
@ -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).
|
||||
|
|
|
@ -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 <i>[\*]</i> for array variable expansion.
|
||||
|
||||
Using the <i>[\*]</i> 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 <i>[\*]</i>
|
||||
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 <i>[\*]</i> 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 <i>[\*]</i> 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 <i>[\*\*]</i>
|
||||
operator. It works similar to the <i>[\*]</i> operator, but additionally collapses nested
|
||||
arrays. How many levels are collapsed is determined by the amount of <i>\*</i> 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 <i>[\*\*]</i> operator on the
|
||||
result. Simplying appending <i>[\*\*]</i> to the query won't help, because *u.friends*
|
||||
is not a nested (multi-dimensional) array, but a simple (one-dimensional) array. Still,
|
||||
the <i>[\*\*]</i> 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 <i>[\*\*]</i> 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"
|
||||
]
|
||||
]
|
||||
```
|
|
@ -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.
|
||||
|
||||
|
|
@ -201,6 +201,12 @@ will produce the following result:
|
|||
|
||||
[ 2010, 2011, 2012, 2013 ]
|
||||
|
||||
|
||||
!SUBSUBSECTION Array operators
|
||||
|
||||
AQL provides [array operators](ArrayOperators.md) <i>[\*]</i> for array variable expansion and <i>[\*\*]</i> for array contraction.
|
||||
|
||||
|
||||
!SUBSUBSECTION Operator precedence
|
||||
|
||||
The operator precedence in AQL is similar as in other familiar languages (lowest precedence first):
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue