ArangoDB v2.8 reached End of Life (EOL) and is no longer supported.
This documentation is outdated. Please see the most recent version here: Try latest
Advanced features
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:
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 }
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.
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:
[
{
"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:
[
{ "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:
[
[
"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"
]
]
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:
[
[
"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
)[**]
[
[
"tina",
"helga",
"alfred",
"sergei",
"tiffany",
"bob",
"elena"
]
]