1
0
Fork 0
arangodb/Doxygen/doc/Aql.html

763 lines
61 KiB
HTML

<html><head><title>ArangoDB Manual</title> <style media="screen" type="text/css" style="display:none">body{background-color:white;font:13px Helvetica,arial,freesans,clean,sans-serif;line-height:1.4;color:#333;}#access{font-size:16px;margin-left:12px;display:block;margin-left:10px;margin-right:10px;background-color:#F3F1EE!important;}#access a{border-right:1px solid #DBDEDF;color:#A49F96;display:block;line-height:38px;padding:0 10px;text-decoration:none;}#navigation ul{text-transform:uppercase;list-style:none;margin:0;}#navigation li{float:left;position:relative;}#container{width:920px;margin:0 auto;}a{color:#4183C4;text-decoration:none;}.contents h2{font-size:24px;border-bottom:1px solid #CCC;color:black;}.contents h1{font-size:33px;border-bottom:1px solid #CCC;color:black;}.clearfix:after{content:".";display:block;clear:both;font-size:0;height:0;visibility:hidden;}/**/ *:first-child+html .clearfix{min-height:0;}/**/ * html .clearfix{height:1%;}</style></head><body><div id="container"><img src="images/logo_arangodb.png" width="397" height="67" alt="ArangoDB"><div id="access" role="navigation"><div id="navigation"><ul id="menu-ahome" class="menu"><li><a href="Home.html">Table of contents</a></li> <li><a href="http://www.arangodb.org">ArangoDB homepage</a></li></ul></div><div class="clearfix"></div></div><div>
<!-- Generated by Doxygen 1.7.5.1 -->
</div>
<div class="header">
<div class="headertitle">
<h1>ArangoDB Query Language (AQL) </h1> </div>
</div>
<div class="contents">
<div class="textblock"><hr/>
<ul>
<li>
<a class="el" href="Aql.html">ArangoDB Query Language (AQL)</a> <ul>
<li>
<a class="el" href="Aql.html#AqlPurpose">Introduction</a> </li>
<li>
<a class="el" href="Aql.html#AqlHowToUse">How to invoke AQL</a> </li>
<li>
<a class="el" href="Aql.html#AqlQueryResults">Query results</a> </li>
<li>
<a class="el" href="Aql.html#AqlBasics">Language basics</a> <ul>
<li>
<a class="el" href="Aql.html#AqlWhitespace">Whitespace</a> </li>
<li>
<a class="el" href="Aql.html#AqlComments">Comments</a> </li>
<li>
<a class="el" href="Aql.html#AqlKeywords">Keywords</a> </li>
<li>
<a class="el" href="Aql.html#AqlNames">Names</a> </li>
<li>
<a class="el" href="Aql.html#AqlTypes">Data types</a> </li>
<li>
<a class="el" href="Aql.html#AqlParameter">Bind parameters</a> </li>
<li>
<a class="el" href="Aql.html#AqlTypeOrder">Type and value order</a> </li>
<li>
<a class="el" href="Aql.html#AqlData">Accessing data from collections</a> </li>
<li>
<a class="el" href="Aql.html#AqlOperators">Operators</a> </li>
<li>
<a class="el" href="Aql.html#AqlFunctions">Functions</a> </li>
</ul>
</li>
<li>
<a class="el" href="Aql.html#AqlOperations">High-level operations</a> <ul>
<li>
<a class="el" href="Aql.html#AqlOperationFor">FOR</a> </li>
<li>
<a class="el" href="Aql.html#AqlOperationReturn">RETURN</a> </li>
<li>
<a class="el" href="Aql.html#AqlOperationFilter">FILTER</a> </li>
<li>
<a class="el" href="Aql.html#AqlOperationSort">SORT</a> </li>
<li>
<a class="el" href="Aql.html#AqlOperationLimit">LIMIT</a> </li>
<li>
<a class="el" href="Aql.html#AqlOperationLet">LET</a> </li>
<li>
<a class="el" href="Aql.html#AqlOperationCollect">COLLECT</a> </li>
</ul>
</li>
<li>
<a class="el" href="Aql.html#AqlAdvanced">Advanced features</a> <ul>
<li>
<a class="el" href="Aql.html#AqlSubqueries">Subqueries</a> </li>
<li>
<a class="el" href="Aql.html#AqlExpansion">Variable expansion</a> </li>
</ul>
</li>
</ul>
</li>
</ul>
<hr/>
<h2><a class="anchor" id="AqlPurpose"></a>
Introduction</h2>
<p>The ArangoDB query language (AQL) can be used to retrieve data that is stored in ArangoDB. The general workflow when executing a query is as follows:</p>
<ul>
<li>a client application ships an AQL query to the ArangoDB server. The query text contains everything ArangoDB needs to compile the result set.</li>
<li>ArangoDB will parse the query, execute it and compile the results. If the query is invalid or cannot be executed, the server will return an error that the client can process and react to. If the query can be executed successfully, the server will return the query results to the client</li>
</ul>
<p>AQL is mainly a declarative language, meaning that in a query it is expressed what result should be achieved and not how. AQL aims to be human- readable and therefore uses keywords from the English language. Another design goal of AQL was client independency, meaning that the language and syntax are the same for all clients, no matter what programming language the clients might use. Further design goals of AQL were to support complex query patterns, and to support the different data models ArangoDB offers.</p>
<p>In its purpose, AQL is similar to the Structured Query Language (SQL), but the two languages have major syntactic differences. Furthermore, to avoid any confusion between the two languages, the keywords in AQL have been chosen to be different from the keywords used in SQL.</p>
<p>AQL currently supports reading data only. That means you can use the language to issue read-requests on your database, but modifying data via AQL is currently not supported.</p>
<p>For some example queries, please refer to the page <a class="el" href="AqlExamples.html">ArangoDB Query Language (AQL) Examples</a>.</p>
<h2><a class="anchor" id="AqlHowToUse"></a>
How to invoke AQL</h2>
<p>You can run AQL queries from your application via the HTTP REST API. The full API description is available at <a class="el" href="HttpCursor.html">HTTP Interface for AQL Query Cursors</a>.</p>
<p>You can also run AQL queries from arangosh. To do so, first create an ArangoStatement object as follows: </p>
<div class="fragment"><pre class="fragment"> arangosh&gt; stmt = db._createStatement( { <span class="stringliteral">&quot;query&quot;</span>: <span class="stringliteral">&quot;FOR i IN [ 1, 2 ] RETURN i * 2&quot;</span> } );
[<span class="keywordtype">object</span> ArangoStatement]
</pre></div><p>To execute the query, use the <code>execute</code> method: </p>
<div class="fragment"><pre class="fragment"> arangosh&gt; c = stmt.execute();
[<span class="keywordtype">object</span> ArangoQueryCursor]
</pre></div><p> This has executed the query. The query results are available in a cursor now. The cursor can return all its results at once using the <code>elements</code> method: </p>
<div class="fragment"><pre class="fragment"> arangosh&gt; c.elements();
[2, 4]
</pre></div><p>To execute a query using bind parameters, you need to create a statement first and then bind the parameters to it before execution: </p>
<div class="fragment"><pre class="fragment"> arangosh&gt; stmt = db._createStatement( { <span class="stringliteral">&quot;query&quot;</span>: <span class="stringliteral">&quot;FOR i IN [ @one, @two ] RETURN i * 2&quot;</span> } );
[<span class="keywordtype">object</span> ArangoStatement]
arangosh&gt; stmt.bind(<span class="stringliteral">&quot;one&quot;</span>, 1);
arangosh&gt; stmt.bind(<span class="stringliteral">&quot;two&quot;</span>, 2);
arangosh&gt; c = stmt.execute();
[<span class="keywordtype">object</span> ArangoQueryCursor]
</pre></div><p> The cursor results can then be dumped or traversed: </p>
<div class="fragment"><pre class="fragment"> arangosh&gt; <span class="keywordflow">while</span> (c.hasNext()) { print(c.next()); }
2
4
</pre></div><p> Please note that each cursor can be used exactly once as they are forward-only. Once all cursor results have been dumped or iterated, the cursor is empty. To iterate through the results again, the query needs to be re-executed.</p>
<p>Please also note that when using bind parameters, you must not re-declare an existing bind parameter because this will be considered an error: </p>
<div class="fragment"><pre class="fragment"> arangosh&gt; stmt = db._createStatement( { <span class="stringliteral">&quot;query&quot;</span>: <span class="stringliteral">&quot;FOR i IN [ @one, @two ] RETURN i * 2&quot;</span> } );
[<span class="keywordtype">object</span> ArangoStatement]
arangosh&gt; stmt.bind(<span class="stringliteral">&quot;one&quot;</span>, 1);
arangosh&gt; stmt.bind(<span class="stringliteral">&quot;one&quot;</span>, 1);
JavaScript exception in file <span class="stringliteral">&#39;client/client.js&#39;</span> at 771,9: redeclaration of bind parameter
</pre></div><h2><a class="anchor" id="AqlQueryResults"></a>
Query results</h2>
<h3><a class="anchor" id="AqlQueryResultsSet"></a>
Result sets</h3>
<p>The result of an AQL query is a list of values. The individual values in the result list may or may not have a homogenuous structure, depending on what is actually queried.</p>
<p>For example, when returning data from a collection with inhomogenuous documents (the individual documents in the collection have different attribute names) without modification, the result values will as well have an inhomogenuous structure. Each result value itself is a document:</p>
<div class="fragment"><pre class="fragment">FOR u IN users
RETURN u
[ { "id" : 1, "name" : "John", "active" : false },
{ "age" : 32, "id" : 2, "name" : "Vanessa" },
{ "friends" : [ "John", "Vanessa" ], "id" : 3, "name" : "Amy" } ]
</pre></div> <p>However, if a fixed set of attributes from the collection is queried, then the query result values will have a homogenuous structure. Each result value is still a document:</p>
<div class="fragment"><pre class="fragment">FOR u IN users
RETURN { "id" : u.id, "name" : u.name }
[ { "id" : 1, "name" : "John" },
{ "id" : 2, "name" : "Vanessa" },
{ "id" : 3, "name" : "Amy" } ]
</pre></div> <p>It is also possible to query just scalar values. In this case, the result set is a list of scalars, and each result value is a scalar value:</p>
<div class="fragment"><pre class="fragment">FOR u IN users
RETURN u.id
[ 1, 2, 3 ]
</pre></div> <p>If a query does not produce any results because no matching data can be found, it will produce an empty result list:</p>
<div class="fragment"><pre class="fragment">[ ]
</pre></div> <h3><a class="anchor" id="AqlQueryResultsErrors"></a>
Errors</h3>
<p>Issuing an invalid query to the server will result in a parse error if the query is syntactically invalid. ArangoDB will detect such errors during query inspection and abort further processing. Instead, the error number and an error message are returned so that the errors can be fixed.</p>
<p>If a query passes the parsing stage, all collections referenced in the query will be opened. If any of the referenced collections is not present, query execution will again be aborted and an appropriate error message will be returned.</p>
<p>Executing a query might also produce run-time errors under some circumstances that cannot be predicted from inspecting the query text alone. This is because queries might use data from collections that might also be inhomogenuous. Some examples that will cause run-time errors are:</p>
<ul>
<li>division by zero: will be triggered when an attempt is made to use the value 0 as the divisor in an arithmetic division or modulus operation</li>
<li>invalid operands for arithmetic operations: will be triggered when an attempt is made to use any non-numeric values as operands in arithmetic operations. This includes unary (unary minus, unary plus) and binary operations (plus, minus, multiplication, division, and modulus)</li>
<li>invalid operands for logical operations: will be triggered when an attempt is made to use any non-boolean values as operand(s) in logical operations. This includes unary (logical not/negation), binary (logical and, logical or), and the ternary operators.</li>
</ul>
<p>Please refer to the <a class="el" href="ArangoErrors.html">Error codes and meanings</a> page for a list of error codes and meanings.</p>
<h2><a class="anchor" id="AqlBasics"></a>
Language basics</h2>
<h3><a class="anchor" id="AqlWhitespace"></a>
Whitespace</h3>
<p>Whitespace can be used in the query text to increase its readability. However, for the parser any whitespace (spaces, carriage returns, line feeds, and tab stops) does not have any special meaning except that it separates individual tokens in the query. Whitespace within strings or names must be enclosed in quotes in order to be preserved.</p>
<h3><a class="anchor" id="AqlComments"></a>
Comments</h3>
<p>Comments can be embedded at any position in a query. The text contained in the comment is ignored by the language parser. Comments cannot be nested, meaning the comment text may not contain another comment.</p>
<div class="fragment"><pre class="fragment">/* this is a comment */ RETURN 1
/* these */ RETURN /* are */ 1 /* multiple */ + /* comments */ 1
</pre></div> <h3><a class="anchor" id="AqlKeywords"></a>
Keywords</h3>
<p>On the top level, AQL offers the following operations:</p>
<ul>
<li>FOR: list iteration</li>
<li>RETURN: results projection</li>
<li>FILTER: results filtering</li>
<li>SORT: result sorting</li>
<li>LIMIT: result slicing</li>
<li>LET: variable assignment</li>
<li>COLLECT: result grouping</li>
</ul>
<p>Each of the above operations can be initiated in a query by using a keyword of the same name. An AQL query can (and typically does) consist of multiple of the above operations.</p>
<p>An example AQL query might look like this:</p>
<div class="fragment"><pre class="fragment">FOR u IN users
FILTER u.type == "newbie" &amp;&amp; u.active == true
RETURN u.name
</pre></div> <p>In this example query, the terms <code>FOR</code>, <code>FILTER</code>, and <code>RETURN</code> initiate the higher-level operation according to their name. These terms are also keywords, meaning that they have a special meaning in the language.</p>
<p>For example, the query parser will use the keywords to find out which high-level operations to execute. That also means keywords can only be used at certains locations in a query. This also makes all keywords reserved words that must not be used for other purposes than they are intended for.</p>
<p>For example, it is not possible to use a keyword as a collection or attribute name. If a collection or attribute need to have the same name as a keyword, the collection or attribute name needs to be quoted.</p>
<p>Keywords are case-insensitive, meaning they can be specified in lower, upper, or mixed case in queries. In this documentation, all keywords are written in upper case to make them distinguishable from other query parts.</p>
<p>In addition to the higher-level operations keywords, there are other keywords. The current list of keywords is:</p>
<ul>
<li>FOR</li>
<li>RETURN</li>
<li>FILTER</li>
<li>SORT</li>
<li>LIMIT</li>
<li>LET</li>
<li>COLLECT</li>
<li>ASC</li>
<li>DESC</li>
<li>IN</li>
<li>INTO</li>
<li>NULL</li>
<li>TRUE</li>
<li>FALSE</li>
</ul>
<p>Additional keywords might be added in future versions of ArangoDB.</p>
<h3><a class="anchor" id="AqlNames"></a>
Names</h3>
<p>In general, names are used to identify objects (collections, attributes, variables, and functions) in AQL queries.</p>
<p>The maximum supported length of any name is 64 bytes. Names in AQL are always case-sensitive.</p>
<p>Keywords must not be used as names. If a reserved keyword should be used as a name, the name must be enclosed in backticks. Enclosing a name in backticks allows using otherwise-reserved keywords as names. An example for this is:</p>
<div class="fragment"><pre class="fragment">FOR f IN `filter`
RETURN f.`sort`
</pre></div> <p>Due to the backticks, <code>filter</code> and <code>sort</code> are interpreted as names and not as keywords here.</p>
<h4><a class="anchor" id="AqlCollectionNames"></a>
Collection names</h4>
<p>Collection names can be used in queries as they are. If a collection happens to have the same name as a keyword, the name must be enclosed in backticks.</p>
<p>Allowed characters in collection names are the letters <code>a</code> to <code>z</code> (both in lower and upper case) and the numbers <code>0</code> to <code>9</code> and the the underscore (<code>_</code>) symbol. A collection name must start with either a letter or a number, but not with an underscore.</p>
<h4><a class="anchor" id="AqlAttributeNames"></a>
Attribute names</h4>
<p>When referring to attributes of documents from a collection, the fully qualified attribute name must be used. This is because multiple collections with ambigious attribute names might be used in a query. To avoid any ambiguity, it is not allowed to refer to an unqualified attribute name.</p>
<div class="fragment"><pre class="fragment">FOR u IN users
FOR f IN friends
FILTER u.active == true &amp;&amp; f.active == true &amp;&amp; u.id == f.userId
RETURN u.name
</pre></div> <p>In the above example, the attribute names <code>active</code>, <code>name</code>, <code>id</code>, and <code>userId</code> are qualified using the collection names they belong to (<code>u</code> and <code>f</code> respectively).</p>
<h4><a class="anchor" id="AqlVariableNames"></a>
Variable names</h4>
<p>AQL offers the user to assign values to additional variables in a query. All variables that are assigned a value must have a name that is unique within the context of the query. Variable names must be different from the names of any collection name used in the same query.</p>
<div class="fragment"><pre class="fragment">FOR u IN users
LET friends = u.friends
RETURN { "name" : u.name, "friends" : friends }
</pre></div> <p>In the above query, <code>users</code> is a collection name, and both <code>u</code> and <code>friends</code> are variable names. This is because the <code>FOR</code> and <code>LET</code> operations need target variables to store their intermediate results.</p>
<p>Allowed characters in variable names are the letters <code>a</code> to <code>z</code> (both in lower and upper case), the numbers <code>0</code> to <code>9</code> and the underscore (<code>_</code>) symbol. A variable name must not start with a number. If a variable name starts with the underscore character, it must also contain at least one letter (a-z or A-Z).</p>
<h3><a class="anchor" id="AqlTypes"></a>
Data types</h3>
<p>AQL supports both primitive and compound data types. The following types are available:</p>
<ul>
<li>primitive types: consisting of exactly one value<ul>
<li>null: an empty value, also: the absence of a value</li>
<li>bool: boolean truth value with possible values <code>false</code> and <code>true</code></li>
<li>number: signed (real) number</li>
<li>string: UTF-8 encoded text value</li>
</ul>
</li>
<li>compound types: consisting of multiple values<ul>
<li>list: sequence of values, referred to by their positions</li>
<li>document: sequence of values, referred to by their names</li>
</ul>
</li>
</ul>
<h4><a class="anchor" id="AqlLiteralsNumber"></a>
Numeric literals</h4>
<p>Numeric literals can be integers or real values. They can optionally be signed using the <code>+</code> or <code>-</code> symbols. The scientific notation is also supported.</p>
<div class="fragment"><pre class="fragment">1
42
-1
-42
1.23
-99.99
0.1
-4.87e103
</pre></div><p>All numeric values are treated as 64-bit double-precision values internally. The internal format used is IEEE 754.</p>
<h4><a class="anchor" id="AqlLiteralsString"></a>
String literals</h4>
<p>String literals must be enclosed in single or double quotes. If the used quote character is to be used itself within the string literal, it must be escaped using the backslash symbol. Backslash literals themselves also be escaped using a backslash.</p>
<div class="fragment"><pre class="fragment">"yikes!"
"don't know"
"this is a \"quoted\" word"
"this is a longer string."
"the path separator on Windows is \\"
'yikes!'
'don\'t know'
'this is a longer string."
'the path separator on Windows is \\'
</pre></div><p>All string literals must be UTF-8 encoded. It is currently not possible to use arbitrary binary data if it is not UTF-8 encoded. A workaround to use binary data is to encode the data using base64 or other algorithms on the application side before storing, and decoding it on application side after retrieval.</p>
<h4><a class="anchor" id="AqlCompoundLists"></a>
Lists</h4>
<p>AQL supports two compound types:</p>
<ul>
<li>lists: a composition of unnamed values, each accessible by their positions</li>
<li>documents: a composition of named values, each accessible by their names</li>
</ul>
<p>The first supported compound type is the list type. Lists are effectively sequences of (unnamed/anonymous) values. Individual list elements can be accessed by their positions. The order of elements in a list is important.</p>
<p>An <code>list-declaration</code> starts with the <code>[</code> symbol and ends with the <code>]</code> symbol. A <code>list-declaration</code> contains zero or many <code>expression</code>s, seperated from each other with the <code>,</code> symbol.</p>
<p>In the easiest case, a list is empty and thus looks like:</p>
<div class="fragment"><pre class="fragment">[ ]
</pre></div><p>List elements can be any legal <code>expression</code> values. Nesting of lists is supported.</p>
<div class="fragment"><pre class="fragment">[ 1, 2, 3 ]
[ -99, "yikes!", [ true, [ "no"], [ ] ], 1 ]
[ [ "fox", "marshal" ] ]
</pre></div><p>Individual list values can later be accesses by their positions using the <code>[]</code> accessor. The position of the accessed element must be a numeric value. Positions start at 0.</p>
<div class="fragment"><pre class="fragment">u.friends[2]
</pre></div><h4><a class="anchor" id="AqlCompoundDocuments"></a>
Documents</h4>
<p>The other supported compound type is the document type. Documents are a composition of zero to many attributes. Each attribute is a name/value pair. Document attributes can be accessed individually by their names.</p>
<p>Document declarations start with the <code>{</code> symbol and end with the <code>}</code> symbol. A document contains zero to many attribute declarations, seperated from each other with the <code>,</code> symbol. In the simplest case, a document is empty. Its declaration would then be:</p>
<div class="fragment"><pre class="fragment">{ }
</pre></div><p>Each attribute in a document is a name/value pair. Name and value of an attribute are separated using the <code>:</code> symbol.</p>
<p>The attribute name is mandatory and must be specified as a quoted or unquoted string. If a keyword is to be used as an attribute name, the name must be quoted.</p>
<p>Any valid expression can be used as an attribute value. That also means nested documents can be used as attribute values</p>
<div class="fragment"><pre class="fragment">{ name : "Peter" }
{ "name" : "Vanessa", "age" : 15 }
{ "name" : "John", likes : [ "Swimming", "Skiing" ], "address" : { "street" : "Cucumber lane", "zip" : "94242" } }
</pre></div><p>Individual document attributes can later be accesses by their names using the <code>.</code> accessor. If a non-existing attribute is accessed, the result is <code>null</code>.</p>
<div class="fragment"><pre class="fragment">u.address.city.name
u.friends[0].name.first
</pre></div><h3><a class="anchor" id="AqlParameter"></a>
Bind parameters</h3>
<p>AQL supports the usage of bind parameters, thus allowing to separate the query text from literal values used in the query. It is good practice to separate the query text from the literal values because this will prevent (malicious) injection of keywords and other collection names into an existing query. This injection would be dangerous because it might change the meaning of an existing query.</p>
<p>Using bind parameters, the meaning of an existing query cannot be changed. Bind parameters can be used everywhere in a query where literals can be used.</p>
<p>The syntax for bind parameters is <code>@name</code> where <code>name</code> is the actual parameter name. The bind parameter values need to be passed along with the query when it is executed, but not as part of the query text itself. Please refer to the <a class="el" href="HttpCursor.html#HttpCursorHttp">Accessing Cursors via HTTP</a> manual section for information about how to pass the bind parameter values to the server.</p>
<div class="fragment"><pre class="fragment">FOR u IN users
FILTER u.id == @id &amp;&amp; u.name == @name
RETURN u
</pre></div> <p>Bind parameter names must start with any of the letters <code>a</code> to <code>z</code> (both in lower and upper case) or a digit (<code>0</code> to <code>9</code>), and can be followed by any letter, digit, or the underscore symbol.</p>
<p>A special type of bind parameter exists for injecting collection names. This type of bind parameter has a name prefixed with an additional <code>@</code> symbol (thus when using the bind parameter in a query, two <code>@</code> symbols must be used.</p>
<div class="fragment"><pre class="fragment">FOR u IN @@collection
FILTER u.active == true
RETURN u
</pre></div> <h3><a class="anchor" id="AqlTypeOrder"></a>
Type and value order</h3>
<p>When checking for equality or inequality or when determining the sort order of values, AQL uses a deterministic algorithm that takes both the data types and the actual values into account.</p>
<p>The compared operands are first compared by their data types, and only by their data values if the operands have the same data types.</p>
<p>The following type order is used when comparing data types:</p>
<div class="fragment"><pre class="fragment">null &lt; bool &lt; number &lt; string &lt; list &lt; document
</pre></div><p>This means <code>null</code> is the smallest type in AQL, and <code>document</code> is the type with the highest order. If the compared operands have a different type, then the comparison result is determined and the comparison is finished.</p>
<p>For example, the boolean <code>true</code> value will always be less than any numeric or string value, any list (even an empty list) or any document. Additionally, any string value (even an empty string) will always be greater than any numeric value, a boolean value, <code>true</code>, or <code>false</code>.</p>
<div class="fragment"><pre class="fragment">null &lt; false
null &lt; true
null &lt; 0
null &lt; ''
null &lt; ' '
null &lt; '0'
null &lt; 'abc'
null &lt; [ ]
null &lt; { }
false &lt; true
false &lt; 0
false &lt; ''
false &lt; ' '
false &lt; '0'
false &lt; 'abc'
false &lt; [ ]
false &lt; { }
true &lt; 0
true &lt; ''
true &lt; ' '
true &lt; '0'
true &lt; 'abc'
true &lt; [ ]
true &lt; { }
0 &lt; ''
0 &lt; ' '
0 &lt; '0'
0 &lt; 'abc'
0 &lt; [ ]
0 &lt; { }
'' &lt; ' '
'' &lt; '0'
'' &lt; 'abc'
'' &lt; [ ]
'' &lt; { }
[ ] &lt; { }
</pre></div><p>If the two compared operands have the same data types, then the operands values are compared. For the primitive types (null, boolean, number, and string), the result is defined as follows:</p>
<ul>
<li>null: <code>null</code> is equal to <code>null</code></li>
<li>boolean:<code>false</code> is less than <code>true</code></li>
<li>number: numeric values are ordered by their cardinal value</li>
<li>string: string values are ordered using a byte-wise comparison</li>
</ul>
<p>Note: unlike in SQL, <code>null</code> can be compared to any value, including <code>null</code> itself, without the result being converted into <code>null</code> automatically.</p>
<p>For compound, types the following special rules are applied:</p>
<p>Two list values are compared by comparing their individual elements position by position, starting at the first element. For each position, the element types are compared first. If the types are not equal, the comparison result is determined, and the comparison is finished. If the types are equal, then the values of the two elements are compared. If one of the lists is finished and the other list still has an element at a compared position, then <code>null</code> will be used as the element value of the fully traversed list.</p>
<p>If a list element is itself a compound value (a list or a document), then the comparison algorithm will check the element's sub values recursively. element's sub elements are compared recursively.</p>
<div class="fragment"><pre class="fragment">[ ] &lt; [ 0 ]
[ 1 ] &lt; [ 2 ]
[ 1, 2 ] &lt; [ 2 ]
[ 99, 99 ] &lt; [ 100 ]
[ false ] &lt; [ true ]
[ false, 1 ] &lt; [ false, '' ]
</pre></div><p>Two documents operands are compared by checking attribute names and value. The attribute names are compared first. Before attribute names are compared, a combined list of all attribute names from both operands is created and sorted lexicographically. This means that the order in which attributes are declared in a document is not relevant when comparing two documents.</p>
<p>The combined and sorted list of attribute names is then traversed, and the respective attributes from the two compared operands are then looked up. If one of the documents does not have an attribute with the sought name, its attribute value is considered to be <code>null</code>. Finally, the attribute value of both documents is compared using the beforementioned data type and value comparison. The comparisons are performed for all document attributes until there is an unambigious comparison result. If an unambigious comparison result is found, the comparison is finished. If there is no unambigious comparison result, the two compared documents are considered equal.</p>
<div class="fragment"><pre class="fragment">[ ] &lt; [ 0 ]
[ 1 ] &lt; [ 2 ]
[ 1, 2 ] &lt; [ 2 ]
[ 99, 99 ] &lt; [ 100 ]
[ false ] &lt; [ true ]
[ false, 1 ] &lt; [ false, '' ]
</pre></div><h3><a class="anchor" id="AqlData"></a>
Accessing data from collections</h3>
<p>Collection data can be accessed by specifying a collection name in a query. A collection can be understood as a list of documents, and that is how they are treated in AQL. Documents from collections are normally accessing using the <code>FOR</code> keyword. Note that when iterating over documents from a collection, the order of documents is undefined. To traverse documents in an explicit and deterministic order, the <code>SORT</code> keyword should be used in addition.</p>
<p>Data in collections is stored in documents, with each document potentially having different attributes than other documents. This is true even for documents of the same collection.</p>
<p>It is therefore quite normal to encounter documents that do not have some or all of the attributes that are queried in an AQL query. In this case, the non-existing attributes in the document will be treated as if they would exist with a value of <code>null</code>. That means that comparing a document attribute to <code>null</code> will return true if the document has the particular attribute and the attribute has a value of <code>null</code>, or that the document does not have the particular attribute at all.</p>
<p>For example, the following query will return all documents from the collection <code>users</code> that have a value of <code>null</code> in the attribute <code>name</code>, plus all documents from <code>users</code> that do not have the <code>name</code> attribute at all:</p>
<div class="fragment"><pre class="fragment">FOR u IN users
FILTER u.name == null
RETURN u
</pre></div> <p>Furthermore, <code>null</code> is less than any other value (excluding <code>null</code> itself). That means documents with non-existing attributes might be included in the result when comparing attribute values with the less than or less equal operators.</p>
<p>For example, the following query with return all documents from the collection <code>users</code> that have an attribute <code>age</code> with a value less than <code>39</code>, but also all documents from the collection that do not have the attribute <code>age</code> at all.</p>
<div class="fragment"><pre class="fragment">FOR u IN users
FILTER u.age &lt; 39
RETURN u
</pre></div> <p>This behavior should always be taken into account when writing queries.</p>
<h3><a class="anchor" id="AqlOperators"></a>
Operators</h3>
<p>AQL supports a number of operators that can be used in expressions. There are comparison, logical, arithmetic, and the ternary operator.</p>
<h4><a class="anchor" id="AqlOperatorsComparison"></a>
Comparison operators</h4>
<p>Comparison (or relational) operators compare two operands. They can be used with any input data types, and will return a boolean result value.</p>
<p>The following comparison operators are supported:</p>
<ul>
<li><code>==</code> equality</li>
<li><code>!=</code> inequality</li>
<li><code>&lt;</code> less than</li>
<li><code>&lt;=</code> less or equal</li>
<li><code>&gt;</code> greater than</li>
<li><code>&gt;=</code> greater or equal</li>
<li><code>in</code> test if a value is contained in a list</li>
</ul>
<p>The <code>in</code> operator expects the second operand to be of type list. All other operators accept any data types for the first and second operands.</p>
<p>Each of the comparison operators returns a boolean value if the comparison can be evaluated and returns <code>true</code> if the comparison evaluates to true, and <code>false</code> otherwise.</p>
<p>Some examples for comparison operations in AQL:</p>
<div class="fragment"><pre class="fragment">1 &gt; 0
true != null
45 &lt;= "yikes!"
65 != "65"
65 == 65
1.23 &lt; 1.32
1.5 IN [ 2, 3, 1.5 ]
</pre></div><h4><a class="anchor" id="AqlOperatorsLogical"></a>
Logical operators</h4>
<p>Logical operators combine two boolean operands in a logical operation and return a boolean result value.</p>
<p>The following logical operators are supported:</p>
<ul>
<li><code>&amp;&amp;</code> logical and operator</li>
<li><code>||</code> logical or operator</li>
<li><code>!</code> logical not/negation operator</li>
</ul>
<p>Some examples for logical operations in AQL:</p>
<div class="fragment"><pre class="fragment">u.age &gt; 15 &amp;&amp; u.address.city != ""
true || false
!u.isInvalid
</pre></div><p>The <code>&amp;&amp;</code>, <code>||</code>, and <code>!</code> operators expect their input operands to be boolean values each. If a non-boolean operand is used, the operation will fail with an error. In case all operands are valid, the result of each logical operator is a boolean value.</p>
<p>Both the <code>&amp;&amp;</code> and <code>||</code> operators use short-circuit evaluation and only evaluate the second operand if the result of the operation cannot be determined by checking the first operand alone.</p>
<h4><a class="anchor" id="AqlOperatorsArithmetic"></a>
Arithmetic operators</h4>
<p>Arithmetic operators perform an arithmetic operation on two numeric operands. The result of an arithmetic operation is again a numeric value. operators are supported:</p>
<p>AQL supports the following arithmetic operators:</p>
<ul>
<li><code>+</code> addition</li>
<li><code>-</code> subtraction</li>
<li><code>*</code> multiplication</li>
<li><code>/</code> division</li>
<li><code>%</code> modulus</li>
</ul>
<p>These operators work with numeric operands only. Invoking any of the operators with non-numeric operands will result in an error. An error will also be raised for some other edge cases as division by zero, numeric over- or underflow etc. If both operands are numeric and the computation result is also valid, the result will be returned as a numeric value.</p>
<p>The unary plus and unary minus are supported as well.</p>
<p>Some example arithmetic operations:</p>
<div class="fragment"><pre class="fragment">1 + 1
33 - 99
12.4 * 4.5
13.0 / 0.1
23 % 7
-15
+9.99
</pre></div><h4><a class="anchor" id="AQLOperatorTernary"></a>
Ternary operator</h4>
<p>AQL also supports a ternary operator that can be used for conditional evaluation. The ternary operator expects a boolean condition as its first operand, and it returns the result of the second operand if the condition evaluates to true, and the third operand otherwise.</p>
<p>Example:</p>
<div class="fragment"><pre class="fragment">u.age &gt; 15 || u.active == true ? u.userId : null
</pre></div><h4><a class="anchor" id="AQLOperatorsPrecedence"></a>
Operator precedence</h4>
<p>The operator precedence in AQL is as follows (lowest precedence first):</p>
<ul>
<li><code>? :</code> ternary operator</li>
<li><code>||</code> logical or</li>
<li><code>&amp;&amp;</code> logical and</li>
<li><code>==</code>, <code>!=</code> equality and inequality</li>
<li><code>in</code> in operator</li>
<li><code>&lt;</code>, <code>&lt;=</code>, <code>&gt;=</code>, <code>&gt;</code> less than, less equal, greater equal, greater than</li>
<li><code>+</code>, <code>-</code> addition, subtraction</li>
<li><code>*</code>, <code>/</code>, <code>%</code> multiplication, division, modulus</li>
<li><code>!</code>, <code>+</code>, <code>-</code> logical negation, unary plus, unary minus</li>
<li><code>[*]</code> expansion</li>
<li><code>()</code> function call</li>
<li><code>.</code> member access</li>
<li><code>[]</code> indexed value access</li>
</ul>
<p>The parentheses <code>(</code> and <code>)</code> can be used to enforce a different operator evaluation order.</p>
<h3><a class="anchor" id="AqlFunctions"></a>
Functions</h3>
<p>AQL supports functions to allow more complex computations. Functions can be called at any query position where an expression is allowed. The general function call syntax is:</p>
<div class="fragment"><pre class="fragment">FUNCTIONAME(arguments)
</pre></div><p>where <code>FUNCTIONNAME</code> is the name of the function to be called, and <code>arguments</code> is a comma-separated list of function arguments. If a function does not need any arguments, the argument list can be left empty. However, even if the argument list is empty the parentheses around it are still mandatory to make function calls distinguishable from variable names.</p>
<p>Some example function calls:</p>
<div class="fragment"><pre class="fragment">HAS(user, "name")
LENGTH(friends)
COLLECTIONS()
</pre></div><p>Function names are not case-sensitive.</p>
<h4><a class="anchor" id="AqlFunctionsCasting"></a>
Type cast functions</h4>
<p>As mentioned before, some of the operators expect their operands to have a certain data type. For example, the logical operators expect their operands to be boolean values, and the arithmetic operators expect their operands to be numeric values. If an operation is performed with operands of an unexpect type, the operation will fail with an error. To avoid such failures, value types can be converted explicitly in a query. This is called type casting.</p>
<p>In an AQL query, type casts are performed only upon request and not implicitly. This helps avoiding unexpected results. All type casts have to be performed by invoking a type cast function. AQL offers several type cast functions for this task. Each of the these functions takes an operand of any data type and returns a result value of type corresponding to the function name (e.g. <code>TO_NUMBER()</code> will return a number value):</p>
<ul>
<li><code>TO_BOOL(<em>value</em>)</code>: takes an input <em>value</em> of any type and converts it into the appropriate boolean value as follows:<ul>
<li><code>null</code> is converted to false.</li>
<li>Numbers are converted to true if they are unequal to 0, and to false otherwise.</li>
<li>Strings are converted to true if they are non-empty, and to false otherwise.</li>
<li>Lists are converted to true if they are non-empty, and to false otherwise.</li>
<li>Documents are converted to true if they are non-empty, and to false otherwise.</li>
</ul>
</li>
<li><code>TO_NUMBER(<em>value</em>)</code>: takes an input <em>value</em> of any type and converts it into a numeric value as follows:<ul>
<li><code>null</code>, false, lists, and documents are converted to the value <code>0</code>.</li>
<li>true is converted to <code>1</code>.</li>
<li>Strings are converted to their numeric equivalent if the full string content is is a valid number, and to <code>0</code> otherwise.</li>
</ul>
</li>
<li><code>TO_STRING(<em>value</em>)</code>: takes an input <em>value</em> of any type and converts it into a string value as follows:<ul>
<li><code>null</code> is converted to the string <code>"null"</code></li>
<li>false is converted to the string <code>"false"</code>, true to the string <code>"true"</code></li>
<li>numbers, lists, and documents are converted to their string equivalents.</li>
</ul>
</li>
</ul>
<h4><a class="anchor" id="AqlFunctionsChecking"></a>
Type check functions</h4>
<p>AQL also offers functions to check the data type of a value at runtime. The following type check functions are available. Each of these functions takes an argument of any data type and returns true if the value has the type that is checked for, and false otherwise.</p>
<p>The following type check functions are available:</p>
<ul>
<li><code>IS_NULL(<em>value</em>)</code>: checks whether <em>value</em> is a <code>null</code> value</li>
<li><code>IS_BOOL(<em>value</em>)</code>: checks whether <em>value</em> is a boolean value</li>
<li><code>IS_NUMBER(<em>value</em>)</code>: checks whether <em>value</em> is a numeric value</li>
<li><code>IS_STRING(<em>value</em>)</code>: checks whether <em>value</em> is a string value</li>
<li><code>IS_LIST(<em>value</em>)</code>: checks whether <em>value</em> is a list value</li>
<li><code>IS_DOCUMENT(<em>value</em>)</code>: checks whether <em>value</em> is a document value</li>
</ul>
<h4><a class="anchor" id="AqlFunctionsString"></a>
String functions</h4>
<p>For string processing, AQL offers the following functions:</p>
<ul>
<li><code>CONCAT(<em>value1</em>, <em>value2</em>, ... <em>valuen</em>)</code>: concatenate the strings passed as in <em>value1</em> to <em>valuen</em>. <code>null</code> values are ignored.</li>
<li><code>CONCAT_SEPARATOR(<em>separator</em>, <em>value1</em>, <em>value2</em>, ... <em>valuen</em>)</code>: concatenate the strings passed as arguments <em>value1</em> to <em>valuen</em> using the <em>separator</em> string. <code>null</code> values are ignored.</li>
<li><code>CHAR_LENGTH(<em>value</em>)</code>: return the number of characters in <em>value</em></li>
<li><code>LOWER(<em>value</em>)</code>: lower-case <em>value</em></li>
<li><code>UPPER(<em>value</em>)</code>: upper-case <em>value</em></li>
<li><code>SUBSTRING(<em>value</em>, <em>offset</em>, <em>length</em>)</code>: return a substring of <em>value</em>, starting at <em>offset</em> and with a maximum length of <em>length</em> characters. Offsets start at position 0.</li>
</ul>
<h4><a class="anchor" id="AqlFunctionsNumeric"></a>
Numeric functions</h4>
<p>AQL offers some numeric functions for calculations. The following functions are supported:</p>
<ul>
<li><code>FLOOR(<em>value</em>)</code>: returns the integer closest but not greater to <em>value</em></li>
<li><code>CEIL(<em>value</em>)</code>: returns the integer closest but not less than <em>value</em></li>
<li><code>ROUND(<em>value</em>)</code>: returns the integer closest to <em>value</em></li>
<li><code>ABS(<em>value</em>)</code>: returns the absolute part of <em>value</em></li>
<li><code>RAND()</code>: returns a pseudo-random number between 0 and 1</li>
</ul>
<h4><a class="anchor" id="AqlFunctionsList"></a>
List functions</h4>
<p>AQL supports the following functions to operate on list values:</p>
<ul>
<li><code>LENGTH(<em>list</em>)</code>: returns the length (number of elements) of <em>list</em></li>
<li><code>MIN(<em>list</em>)</code>: returns the smallest element of <em>list</em>. <code>null</code> values are ignored. If the list is empty or only <code>null</code> are contained in the list, the function will return <code>null</code>.</li>
<li><code>MAX(<em>list</em>)</code>: returns the greatest element of <em>list</em>. <code>null</code> values are ignored. If the list is empty or only <code>null</code> are contained in the list, the function will return <code>null</code>.</li>
<li><code>SUM(<em>list</em>)</code>: returns the sum of values of the elements in <em>list</em>. This requires the elements in <em>list</em> to be numbers. <code>null</code> values are ignored. If the list is empty or only <code>null</code> are contained in the list, the function will return <code>null</code>.</li>
<li><code>REVERSE(<em>list</em>)</code>: returns the elements in <em>list</em> in reversed order.</li>
<li><code>FIRST(<em>list</em>)</code>: returns the first element in <em>list</em> or <code>null</code> if the list is empty.</li>
<li><code>LAST(<em>list</em>)</code>: returns the last element in <em>list</em> or <code>null</code> if the list is empty.</li>
<li><code>UNIQUE(<em>list</em>)</code>: returns all unique elements in <em>list</em>. To determine uniqueness, the function will use the comparison order defined in <a class="el" href="Aql.html#AqlTypeOrder">Type and value order</a>. Calling this function might return the unique elements in any order.</li>
</ul>
<p>Apart from these functions, AQL also offers several language constructs (e.g. <code>FOR</code>, <code>SORT</code>, <code>LIMIT</code>, <code>COLLECT</code>) to operate on lists.</p>
<h4><a class="anchor" id="AqlFunctionsDocument"></a>
Document functions</h4>
<p>AQL supports the following functions to operate on document values:</p>
<ul>
<li><code>MERGE(<em>document1</em>, <em>document2</em>, ... <em>documentn</em>)</code>: merges the documents in <em>document1</em> to <em>documentn</em> into a single document. If document attribute keys are ambigious, the merged result will contain the values of the documents contained later in the argument list.</li>
<li><code>HAS(<em>document</em>, <em>attributename</em>)</code>: returns true if <em>document</em> has an attribute named <em>attributename</em>, and false otherwise.</li>
</ul>
<h4><a class="anchor" id="AqlFunctionsGeo"></a>
Geo functions</h4>
<p>AQL offers the following functions to filter data based on geo indexes:</p>
<ul>
<li><code>NEAR(<em>collection</em>, <em>latitude</em>, <em>longitude</em>, <em>limit</em>, <em>distancename</em>)</code>: returns at most <em>limit</em> documents from collection <em>collection</em> that are near <em>latitude</em> and <em>longitude</em>. The result contains at <em>limit</em> documents, returned in any order. If more than <em>limit</em> documents qualify, it is undefined which of the qualifying documents are returned. Optionally, the distances between the specified coordinate (<em>latitude</em> and <em>longitude</em>) and the document coordinates can be returned as well. To make use of that, an attribute name for the distance result has to be specified in the <em>distancename</em> argument. The result documents will contain the distance value in an attribute of that name.</li>
<li><code>WITHIN(<em>collection</em>, <em>latitude</em>, <em>longitude</em>, <em>radius</em>, <em>distancename</em>)</code>: returns all documents from collection <em>collection</em> that are within a radius of <em>radius</em> around that specified coordinate (<em>latitude</em> and <em>longitude</em>). The order in which the result documents are returned is undefined. Optionally, the distance between the coordinate and the document coordinates can be returned as well. To make use of that, an attribute name for the distance result has to be specified in the <em>distancename</em> argument. The result documents will contain the distance value in an attribute of that name.</li>
</ul>
<p>Note: these functions require the collection <em>collection</em> to have at least one geo index. If no geo index can be found, calling this function will fail with an error.</p>
<h4><a class="anchor" id="AqlFunctionsGraph"></a>
Graph functions</h4>
<p>AQL has the following functions to traverse graphs:</p>
<ul>
<li><code>PATHS(<em>vertexcollection</em>, <em>edgecollection</em>, <em>direction</em>, <em>followcycles</em>)</code>: returns a list of paths through the graph defined by the nodes in the collection <em>vertexcollection</em> and edges in the collection <em>edgecollection</em>. For each vertex in <em>vertexcollection</em>, it will determine the paths through the graph depending on the value of <em>direction</em>:<ul>
<li><code>"outbound"</code>: follow all paths that start at the current vertex and lead to another vertex</li>
<li><code>"inbound"</code>: follow all paths that lead from another vertex to the current vertex</li>
<li><code>"any"</code>: combination of <code>"outbound"</code> and <code>"inbound"</code>. The default value for <em>direction</em> is <code>"outbound"</code>. If <em>followcycles</em> is true, cyclic paths will be followed as well. This is turned off by default.</li>
</ul>
</li>
</ul>
<p>The result of the function is a list of paths. Paths of length 0 will also be returned. Each path is a document consisting of the following attributes:</p>
<ul>
<li><em>vertices</em>: list of vertices visited along the path</li>
<li><em>edges</em>: list of edges visited along the path (might be empty)</li>
<li><em>source</em>: start vertex of path</li>
<li><em>destination</em>: destination vertex of path</li>
</ul>
<p>Example calls:</p>
<div class="fragment"><pre class="fragment">PATHS(friends, friendrelations, "outbound", false)
FOR p IN PATHS(friends, friendrelations, "outbound")
FILTER p.source._id == "123456/123456" &amp;&amp; LENGTH(p.edges) == 2
RETURN p.vertices[*].name
</pre></div><h4><a class="anchor" id="AqlFunctionsControl"></a>
Control flow functions</h4>
<p>AQL offers the following functions to let the user control the flow of operations:</p>
<ul>
<li><code>NOT_NULL(<em>condition</em>, <em>alternative</em>)</code>: returns <em>condition</em> if it is not <code>null</code>, and <em>alternative</em> otherwise.</li>
</ul>
<h4><a class="anchor" id="AqlFunctionsMisc"></a>
Miscellaneous functions</h4>
<p>Finally, AQL supports the following functions that do not belong to any of the other function categories:</p>
<ul>
<li><code>COLLECTIONS()</code>: returns a list of collections. Each collection is returned as a document with attributes <code>name</code> and <code>_id</code>.</li>
</ul>
<h2><a class="anchor" id="AqlOperations"></a>
High-level operations</h2>
<h3><a class="anchor" id="AqlOperationFor"></a>
FOR</h3>
<p>The <code>FOR</code> keyword can be to iterate over all elements of a list. The general syntax is:</p>
<div class="fragment"><pre class="fragment">FOR variable-name IN expression
</pre></div><p>Each list element returned by <code>expression</code> is visited exactly once. It is required that <code>expression</code> returns a list in all cases. The empty list is allowed, too. The current list element is made available for further processing in the variable specified by <code>variable-name</code>.</p>
<div class="fragment"><pre class="fragment">FOR u IN users
RETURN u
</pre></div> <p>This will iterate over all elements from the list <code>users</code> (note: this list consists of all documents from the collection named "users" in this case) and make the current list element available in variable <code>u</code>. <code>u</code> is not modified in this example but simply pushed into the result using the <code>RETURN</code> keyword.</p>
<p>Note: when iterating over collection-based lists as shown here, the order of documents is undefined unless an explicit sort order is defined using a <code>SORT</code> statement.</p>
<p>The variable introduced by <code>FOR</code> is available until the scope the <code>FOR</code> is placed in is closed.</p>
<p>Another example that uses a statically declared list of values to iterate over:</p>
<div class="fragment"><pre class="fragment">FOR year IN [ 2011, 2012, 2013 ]
RETURN { "year" : year, "isLeapYear" : year % 4 == 0 &amp;&amp; (year % 100 != 0 || year % 400 == 0) }
</pre></div> <p>Nesting of multiple <code>FOR</code> statements is allowed, too. When <code>FOR</code> statements are nested, a cross product of the list elements returned by the individual <code>FOR</code> statements will be created.</p>
<div class="fragment"><pre class="fragment">FOR u IN users
FOR l IN locations
RETURN { "user" : u, "location" : l }
</pre></div> <p>In this example, there are two list iterations: an outer iteration over the list <code>users</code> plus an inner iteration over the list <code>locations</code>. The inner list is traversed as many times as there are elements in the outer list. For each iteration, the current values of <code>users</code> and <code>locations</code> are made available for further processing in the variable <code>u</code> and <code>l</code>.</p>
<h3><a class="anchor" id="AqlOperationReturn"></a>
RETURN</h3>
<p>The <code>RETURN</code> statement can (and must) be used to produce the result of a query. It is mandatory to specify a <code>RETURN</code> statement at the end of each block in a query, otherwise the query result would be undefined.</p>
<p>The general syntax for <code>return</code> is:</p>
<div class="fragment"><pre class="fragment">RETURN expression
</pre></div><p>The <code>expression</code> returned by <code>RETURN</code> is produced for each iteration the <code>RETURN</code> statement is placed in. That means the result of a <code>RETURN</code> statement is always a list (this includes the empty list). To return all elements from the currently iterated list without modification, the following simple form can be used:</p>
<div class="fragment"><pre class="fragment">FOR variable-name IN expression
RETURN variable-name
</pre></div><p>As <code>RETURN</code> allows specifying an expression, arbitrary computations can be performed to calculate the result elements. Any of the variables valid in the scope the <code>RETURN</code> is placed in can be used for the computations.</p>
<p>Note: return will close the current scope and eliminate all local variables in it.</p>
<h3><a class="anchor" id="AqlOperationFilter"></a>
FILTER</h3>
<p>The <code>FILTER</code> statement can be used to restrict the results to elements that match an arbitrary logical condition. The general syntax is:</p>
<div class="fragment"><pre class="fragment">FILTER condition
</pre></div><p><code>condition</code> must be a condition that evaluates to either <code>false</code> or <code>true</code>. If the condition result is false, the current element is skipped, so it will not be processed further and not be part of the result. If the condition is true, the current element is not skipped and can be further processed.</p>
<div class="fragment"><pre class="fragment">FOR u IN users
FILTER u.active == true &amp;&amp; u.age &lt; 39
RETURN u
</pre></div> <p>In the above example, all list elements from <code>users</code> will be included that have an attribute <code>active</code> with value <code>true</code> and that have an attribute <code>age</code> with a value less than <code>39</code>. All other elements from <code>users</code> will be skipped and not be included the result produced by <code>RETURN</code>.</p>
<p>It is allowed to specifiy multiple <code>FILTER</code> statements in a query, and even in the same block. If multiple <code>FILTER</code> statements are used, their results will be combined with a logical and, meaning all filter conditions must be true to include an element.</p>
<div class="fragment"><pre class="fragment">FOR u IN users
FILTER u.active == true
FILTER u.age &lt; 39
RETURN u
</pre></div> <h3><a class="anchor" id="AqlOperationSort"></a>
SORT</h3>
<p>The <code>SORT</code> statement will force a sort of the list of already produced intermediate results in the current block. <code>SORT</code> allows specifying one or multiple sort criteria and directions. The general syntax is:</p>
<div class="fragment"><pre class="fragment">SORT expression direction
</pre></div><p>Specifiyng the <code>direction</code> is optional. The default (implict) direction for a sort is the ascending order. To explicitly specify the sort direction, the keywords <code>ASC</code> (ascending) and <code>DESC</code> can be used. Multiple sort criteria can be separated using commas.</p>
<p>Note: when iterating over collection-based lists, the order of documents is always undefined unless an explicit sort order is defined using <code>SORT</code>.</p>
<div class="fragment"><pre class="fragment">FOR u IN users
SORT u.lastName, u.firstName, u.id DESC
RETURN u
</pre></div> <h3><a class="anchor" id="AqlOperationLimit"></a>
LIMIT</h3>
<p>The <code>LIMIT</code> statement allows slicing the list of result documents using an offset and a count. It reduces the number of elements in the result to at most the specified number. Two general forms of <code>LIMIT</code> are followed:</p>
<div class="fragment"><pre class="fragment">LIMIT count
LIMIT offset, count
</pre></div><p>The first form allows specifying only the <code>count</code> value whereas the second form allows specifying both <code>offset</code> and <code>count</code>. The first form is identical using the second form with an <code>offset</code> value of <code>0</code>.</p>
<p>The <code>offset</code> value specifies how many elements from the result shall be discarded. It must be 0 or greater. The <code>count</code> value specifies how many elements should be at most included in the result.</p>
<div class="fragment"><pre class="fragment">FOR u IN users
SORT u.firstName, u.lastName, u.id DESC
LIMIT 0, 5
RETURN u
</pre></div> <h3><a class="anchor" id="AqlOperationLet"></a>
LET</h3>
<p>The <code>LET</code> statement can be used to assign an arbitrary value to a variable. The variable is then introduced in the scope the <code>LET</code> statement is placed in. The general syntax is:</p>
<div class="fragment"><pre class="fragment">LET variable-name = expression
</pre></div><p><code>LET</code> statements are mostly used to declare complex computations and to avoid repeated computations of the same value at multiple parts of a query.</p>
<div class="fragment"><pre class="fragment">FOR u IN users
LET numRecommendations = LENGTH(u.recommendations)
RETURN { "user" : u, "numRecommendations" : numRecommendations, "isPowerUser" : numRecommendations &gt;= 10 }
</pre></div> <p>In the above example, the computation of the number of recommendations is factored out using a <code>LET</code> statement, thus avoiding computing the value twice in the <code>RETURN</code> statement.</p>
<p>Another use case for <code>LET</code> is to declare a complex computation in a subquery, making the whole query more readable.</p>
<div class="fragment"><pre class="fragment">FOR u IN users
LET friends = (
FOR f IN friends
FILTER u.id == f.userId
RETURN f
)
LET memberships = (
FOR m IN memberships
FILTER u.id == m.userId
RETURN m
)
RETURN { "user" : u, "friends" : friends, "numFriends" : LENGTH(friends), "memberShips" : memberships }
</pre></div> <h3><a class="anchor" id="AqlOperationCollect"></a>
COLLECT</h3>
<p>The <code>COLLECT</code> keyword can be used to group a list by one or multiple group criteria. The two general syntaxes for <code>COLLECT</code> are:</p>
<div class="fragment"><pre class="fragment">COLLECT variable-name = expression
COLLECT variable-name = expression INTO groups
</pre></div><p>The first form only groups the result by the defined group criteria defined by <code>expression</code>. In order to further process the results produced by <code>COLLECT</code>, a new variable (specified by <code>variable-name</code> is introduced. This variable contains the group value.</p>
<p>The second form does the same as the first form, but additionally introduces a variable (specified by <code>groups</code>) that contains all elements that fell into the group. Specifying the <code>INTO</code> clause is optional-</p>
<div class="fragment"><pre class="fragment">FOR u IN users
COLLECT city = u.city INTO g
RETURN { "city" : city, "users" : g }
</pre></div> <p>In the above example, the list of <code>users</code> will be grouped by the attribute <code>city</code>. The result is a new list of documents, with one element per distinct <code>city</code> value. The elements from the original list (here: <code>users</code>) per city are made available in the variable <code>g</code>. This is due to the <code>INTO</code> clause.</p>
<p><code>COLLECT</code> also allows specifying multiple group criteria. Individual group criteria can be separated by commas.</p>
<div class="fragment"><pre class="fragment">FOR u IN users
COLLECT first = u.firstName, age = u.age INTO g
RETURN { "first" : first, "age" : age, "numUsers" : LENGTH(g) }
</pre></div><p>In the above example, the list of <code>users</code> is grouped by first names and ages first, and for each distinct combination of first name and age, the number of users found is returned.</p>
<p>Note: the <code>COLLECT</code> statement eliminates all local variables in the current scope. After <code>COLLECT</code> only the variables introduced by <code>COLLECT</code> itself are available.</p>
<h2><a class="anchor" id="AqlAdvanced"></a>
Advanced features</h2>
<h3><a class="anchor" id="AqlSubqueries"></a>
Subqueries</h3>
<p>Whereever 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).</p>
<p>It is required that subqueries be put inside parentheses <code>(</code> and <code>)</code> to explicitly mark their start and end points:</p>
<div class="fragment"><pre class="fragment">FOR u IN users
LET recommendations = (
FOR r IN recommendations
FILTER u.id == r.userId
SORT u.rank DESC
LIMIT 10
RETURN r
)
RETURN { "user" : u, "recommendations" : recommendations }
FOR u IN users
COLLECT city = u.city INTO g
RETURN { "city" : city, "numUsers" : LENGTH(g), "maxRating": MAX(
FOR r IN g
RETURN r.user.rating
) }
</pre></div><p>Subqueries might also include other subqueries themselves.</p>
<h3><a class="anchor" id="AqlExpansion"></a>
Variable expansion</h3>
<p>In order to access a named attribute from all elements in a list easily, AQL offers the shortcut operator <code>[\*]</code> for variable expansion.</p>
<p>Using the <code>[\*]</code> operator with a variable will iterate over all elements in the variable thus allowing to access a particular attribute of each element. It is required that the expanded variable is a list. The result of the <code>[\*]</code> operator is again a list.</p>
<div class="fragment"><pre class="fragment">FOR u IN users
RETURN { "user" : u, "friendNames" : u.friends[*].name }
</pre></div><p>In the above example, the attribute <code>name</code> is accessed for each element in the list <code>u.friends</code>. The result is a flat list of friend names, made available as the attribute <code>friendNames</code>. </p>
</div></div>
</div></body></html>