diff --git a/Doxygen/Examples.Ahuacatl/aqlcollect b/Doxygen/Examples.Ahuacatl/aqlcollect new file mode 100644 index 0000000000..fa68a802b2 --- /dev/null +++ b/Doxygen/Examples.Ahuacatl/aqlcollect @@ -0,0 +1,4 @@ +FOR u IN users + COLLECT city = u.city INTO g + RETURN { "city" : city, "users" : g } + diff --git a/Doxygen/Examples.Ahuacatl/aqlcollect2 b/Doxygen/Examples.Ahuacatl/aqlcollect2 new file mode 100644 index 0000000000..480cd01b61 --- /dev/null +++ b/Doxygen/Examples.Ahuacatl/aqlcollect2 @@ -0,0 +1,4 @@ +FOR u IN users + COLLECT first = u.firstName, age = u.age INTO g + RETURN { "first" : first, "age" : age, "numUsers" : LENGTH(g) } + diff --git a/Doxygen/Examples.Ahuacatl/aqlcollectsyntax b/Doxygen/Examples.Ahuacatl/aqlcollectsyntax new file mode 100644 index 0000000000..cea121e8f7 --- /dev/null +++ b/Doxygen/Examples.Ahuacatl/aqlcollectsyntax @@ -0,0 +1,2 @@ +COLLECT variable-name = expression +COLLECT variable-name = expression INTO groups diff --git a/Doxygen/Examples.Ahuacatl/aqlexpansion b/Doxygen/Examples.Ahuacatl/aqlexpansion new file mode 100644 index 0000000000..d32d344b74 --- /dev/null +++ b/Doxygen/Examples.Ahuacatl/aqlexpansion @@ -0,0 +1,2 @@ +FOR u IN users + RETURN { "user" : u, "friendNames" : u.friends[*].name } diff --git a/Doxygen/Examples.Ahuacatl/aqlfilter b/Doxygen/Examples.Ahuacatl/aqlfilter new file mode 100644 index 0000000000..0711936186 --- /dev/null +++ b/Doxygen/Examples.Ahuacatl/aqlfilter @@ -0,0 +1,3 @@ +FOR u IN users + FILTER u.active == true && u.age < 39 + RETURN u diff --git a/Doxygen/Examples.Ahuacatl/aqlfiltermultiple b/Doxygen/Examples.Ahuacatl/aqlfiltermultiple new file mode 100644 index 0000000000..0b1b4f364d --- /dev/null +++ b/Doxygen/Examples.Ahuacatl/aqlfiltermultiple @@ -0,0 +1,4 @@ +FOR u IN users + FILTER u.active == true + FILTER u.age < 39 + RETURN u diff --git a/Doxygen/Examples.Ahuacatl/aqlfiltersyntax b/Doxygen/Examples.Ahuacatl/aqlfiltersyntax new file mode 100644 index 0000000000..730d0619fe --- /dev/null +++ b/Doxygen/Examples.Ahuacatl/aqlfiltersyntax @@ -0,0 +1 @@ +FILTER condition diff --git a/Doxygen/Examples.Ahuacatl/aqlfor b/Doxygen/Examples.Ahuacatl/aqlfor new file mode 100644 index 0000000000..6f2a113626 --- /dev/null +++ b/Doxygen/Examples.Ahuacatl/aqlfor @@ -0,0 +1,2 @@ +FOR u IN users + RETURN u diff --git a/Doxygen/Examples.Ahuacatl/aqlfornested b/Doxygen/Examples.Ahuacatl/aqlfornested new file mode 100644 index 0000000000..333f65f25b --- /dev/null +++ b/Doxygen/Examples.Ahuacatl/aqlfornested @@ -0,0 +1,3 @@ +FOR u IN users + FOR l IN locations + RETURN { "user" : u, "location" : l } diff --git a/Doxygen/Examples.Ahuacatl/aqlforstatic b/Doxygen/Examples.Ahuacatl/aqlforstatic new file mode 100644 index 0000000000..6bfae68e46 --- /dev/null +++ b/Doxygen/Examples.Ahuacatl/aqlforstatic @@ -0,0 +1,2 @@ +FOR year IN [ 2011, 2012, 2013 ] + RETURN { "year" : year, "isLeapYear" : year % 4 == 0 && (year % 100 != 0 || year % 400 == 0) } diff --git a/Doxygen/Examples.Ahuacatl/aqlforsyntax b/Doxygen/Examples.Ahuacatl/aqlforsyntax new file mode 100644 index 0000000000..4abc94ad35 --- /dev/null +++ b/Doxygen/Examples.Ahuacatl/aqlforsyntax @@ -0,0 +1 @@ +FOR variable-name IN expression diff --git a/Doxygen/Examples.Ahuacatl/aqlfunctionsyntax b/Doxygen/Examples.Ahuacatl/aqlfunctionsyntax new file mode 100644 index 0000000000..467b97e1c2 --- /dev/null +++ b/Doxygen/Examples.Ahuacatl/aqlfunctionsyntax @@ -0,0 +1 @@ +FUNCTIONAME(arguments) diff --git a/Doxygen/Examples.Ahuacatl/aqllet b/Doxygen/Examples.Ahuacatl/aqllet new file mode 100644 index 0000000000..6303c458f1 --- /dev/null +++ b/Doxygen/Examples.Ahuacatl/aqllet @@ -0,0 +1,3 @@ +FOR u IN users + LET numRecommendations = LENGTH(u.recommendations) + RETURN { "user" : u, "numRecommendations" : numRecommendations, "isPowerUser" : numRecommendations >= 10 } diff --git a/Doxygen/Examples.Ahuacatl/aqllet2 b/Doxygen/Examples.Ahuacatl/aqllet2 new file mode 100644 index 0000000000..ce8c5ddd1f --- /dev/null +++ b/Doxygen/Examples.Ahuacatl/aqllet2 @@ -0,0 +1,12 @@ +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 } diff --git a/Doxygen/Examples.Ahuacatl/aqlletsyntax b/Doxygen/Examples.Ahuacatl/aqlletsyntax new file mode 100644 index 0000000000..171d802d6c --- /dev/null +++ b/Doxygen/Examples.Ahuacatl/aqlletsyntax @@ -0,0 +1 @@ +LET variable-name = expression diff --git a/Doxygen/Examples.Ahuacatl/aqllimit b/Doxygen/Examples.Ahuacatl/aqllimit new file mode 100644 index 0000000000..d2c23c52dd --- /dev/null +++ b/Doxygen/Examples.Ahuacatl/aqllimit @@ -0,0 +1,4 @@ +FOR u IN users + SORT u.firstName, u.lastName, u.id DESC + LIMIT 0, 5 + RETURN u diff --git a/Doxygen/Examples.Ahuacatl/aqllimitsyntax b/Doxygen/Examples.Ahuacatl/aqllimitsyntax new file mode 100644 index 0000000000..d350ce2a1b --- /dev/null +++ b/Doxygen/Examples.Ahuacatl/aqllimitsyntax @@ -0,0 +1,2 @@ +LIMIT count +LIMIT offset, count diff --git a/Doxygen/Examples.Ahuacatl/aqlnull b/Doxygen/Examples.Ahuacatl/aqlnull new file mode 100644 index 0000000000..58ad81e681 --- /dev/null +++ b/Doxygen/Examples.Ahuacatl/aqlnull @@ -0,0 +1,3 @@ +FOR u IN users + FILTER u.name == null + RETURN u diff --git a/Doxygen/Examples.Ahuacatl/aqlnull2 b/Doxygen/Examples.Ahuacatl/aqlnull2 new file mode 100644 index 0000000000..2db6f9fa01 --- /dev/null +++ b/Doxygen/Examples.Ahuacatl/aqlnull2 @@ -0,0 +1,3 @@ +FOR u IN users + FILTER u.age < 39 + RETURN u diff --git a/Doxygen/Examples.Ahuacatl/aqlreturn b/Doxygen/Examples.Ahuacatl/aqlreturn new file mode 100644 index 0000000000..6ab0ac137c --- /dev/null +++ b/Doxygen/Examples.Ahuacatl/aqlreturn @@ -0,0 +1,2 @@ +FOR variable-name IN expression + RETURN variable-name diff --git a/Doxygen/Examples.Ahuacatl/aqlreturnsyntax b/Doxygen/Examples.Ahuacatl/aqlreturnsyntax new file mode 100644 index 0000000000..00fd5a7033 --- /dev/null +++ b/Doxygen/Examples.Ahuacatl/aqlreturnsyntax @@ -0,0 +1 @@ +RETURN expression diff --git a/Doxygen/Examples.Ahuacatl/aqlsort b/Doxygen/Examples.Ahuacatl/aqlsort new file mode 100644 index 0000000000..1031937383 --- /dev/null +++ b/Doxygen/Examples.Ahuacatl/aqlsort @@ -0,0 +1,3 @@ +FOR u IN users + SORT u.lastName, u.firstName, u.id DESC + RETURN u diff --git a/Doxygen/Examples.Ahuacatl/aqlsortsyntax b/Doxygen/Examples.Ahuacatl/aqlsortsyntax new file mode 100644 index 0000000000..5c7398dded --- /dev/null +++ b/Doxygen/Examples.Ahuacatl/aqlsortsyntax @@ -0,0 +1 @@ +SORT expression direction diff --git a/Doxygen/Examples.Ahuacatl/aqlstrings b/Doxygen/Examples.Ahuacatl/aqlstrings index 3439db2327..ca1e032659 100644 --- a/Doxygen/Examples.Ahuacatl/aqlstrings +++ b/Doxygen/Examples.Ahuacatl/aqlstrings @@ -1,5 +1,6 @@ "yikes!" "don't know" +"this is a \"quoted\" word" "this is a longer string." "the path separator on Windows is \\" diff --git a/Doxygen/Examples.Ahuacatl/aqlsubquery b/Doxygen/Examples.Ahuacatl/aqlsubquery new file mode 100644 index 0000000000..a0a5ff96d7 --- /dev/null +++ b/Doxygen/Examples.Ahuacatl/aqlsubquery @@ -0,0 +1,17 @@ +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 + ) } diff --git a/Doxygen/Examples.Ahuacatl/aqltypeorder b/Doxygen/Examples.Ahuacatl/aqltypeorder index 7af824998d..1bb4aa85d8 100644 --- a/Doxygen/Examples.Ahuacatl/aqltypeorder +++ b/Doxygen/Examples.Ahuacatl/aqltypeorder @@ -1 +1 @@ -null < false < true < number < string < list < document +null < bool < number < string < list < document diff --git a/RestServer/aql.dox b/RestServer/aql.dox index 2a6029017a..03680ffa13 100644 --- a/RestServer/aql.dox +++ b/RestServer/aql.dox @@ -31,7 +31,7 @@ /// @section AqlPurpose Purpose /// /// The ArangoDB query language (AQL) can be used to retrieve data that is -/// stored in ArangoDB. The general workflow is as follows: +/// stored in ArangoDB. The general workflow when executing a query is as follows: /// - a client application ships an AQL query to the ArangoDB server. The query /// text contains everything ArangoDB needs to compile the result set. /// - ArangoDB will parse the query, execute it and compile the results. If @@ -42,12 +42,17 @@ /// /// 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. +/// 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. /// /// In its purpose, AQL is similar to the Structured Query Language (SQL), -/// but the 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. +/// 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. /// /// @section AqlBasics Language basics /// @@ -178,13 +183,16 @@ /// /// @subsection AqlTypes Data types /// -/// The following data types exist in AQL: -/// - null: an empty value, also: the absence of a value -/// - bool: boolean truth value with possible values @LIT{false} and @LIT{true} -/// - number: signed (real) number -/// - string: UTF-8 encoded text value -/// - list: sequence of values, referred to by their positions -/// - document: sequence of values, referred to by their names +/// AQL supports both primitive and compound data types. The following types are +/// available: +/// - primitive types: consisting of exactly one value +/// - null: an empty value, also: the absence of a value +/// - bool: boolean truth value with possible values @LIT{false} and @LIT{true} +/// - number: signed (real) number +/// - string: UTF-8 encoded text value +/// - compound types: consisting of multiple values +/// - list: sequence of values, referred to by their positions +/// - document: sequence of values, referred to by their names /// /// @subsubsection AqlLiteralsNumber Numeric literals /// @@ -204,7 +212,7 @@ /// escaped using the backslash (@LIT{\\}) symbol. /// Backslash literals themselves also be escaped using a backslash. /// -/// @verbinclude strings +/// @verbinclude aqlstrings /// /// 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 @@ -279,32 +287,12 @@ /// /// @verbinclude aqlbind /// -/// @subsection AqlOperators Operators +/// @subsection AqlTypeOrder Type and value order /// -/// AQL supports a number of operators that can be used in expressions. -/// There are comparison, logical, and arithmetic operators. +/// 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. /// -/// @subsubsection AqlOperatorsComp Comparison operators -/// -/// The following comparison operators are supported: -/// -/// - @LIT{==} equality -/// - @LIT{!=} inequality -/// - @LIT{<} less than -/// - @LIT{<=} less or equal -/// - @LIT{>} greater than -/// - @LIT{>=} greater or equal -/// - @LIT{in} test if a value is contained in a list -/// -/// The @LIT{in} operator expects the second operand to be of type list. All -/// other operators accept any data types for the first and second operands. -/// -/// Each of the comparison operators returns a boolean value if the comparison -/// can be evaluated and returns @LIT{true} if the comparison evaluates to true, -/// and @LIT{false} otherwise. -/// -/// When comparing two operands using one of the above operators, both values and -/// data types are taken into account. /// The compared operands are first compared by their data types, and only by their /// data values if the operands have the same data types. /// @@ -312,7 +300,7 @@ /// /// @verbinclude aqltypeorder /// -/// This means @LIT{null} is the smallest type, and @LIT{document} is the type +/// This means @LIT{null} is the smallest type in AQL, and @LIT{document} 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. /// @@ -325,8 +313,17 @@ /// /// 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 -/// value comparison is simple. For compound, types the following special rules are -/// applied: +/// result is defined as follows: +/// +/// - null: @LIT{null} is equal to @LIT{null} +/// - boolean:@LIT{false} is less than @LIT{true} +/// - number: numeric values are ordered by their cardinal value +/// - string: string values are ordered using a byte-wise comparison +/// +/// Note: unlike in SQL, @LIT{null} can be compared to any value, including @LIT{null} +/// itself, without the result being converted into @LIT{null} automatically. +/// +/// For compound, types the following special rules are applied: /// /// 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 @@ -358,8 +355,79 @@ /// /// @verbinclude aqlcompareexamples2 /// +/// @subsection AqlData Accessing data from collections +/// +/// 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 @LIT{FOR} 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 @LIT{SORT} keyword should be used in addition. +/// +/// 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. +/// +/// 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 @LIT{null}. +/// That means that comparing a document attribute to @LIT{null} will return true +/// if the document has the particular attribute and the attribute has a value of +/// @LIT{null}, or that the document does not have the particular attribute at all. +/// +/// For example, the following query will return all documents from the collection +/// @LIT{users} that have a value of @LIT{null} in the attribute @LIT{name}, plus +/// all documents from @LIT{users} that do not have the @LIT{name} attribute at all: +/// +/// @verbinclude aqlnull +/// +/// Furthermore, @LIT{null} is less than any other value (excluding @LIT{null} +/// 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. +/// +/// For example, the following query with return all documents from the collection +/// @LIT{users} that have an attribute @LIT{age} with a value less than @LIT{39}, but +/// also all documents from the collection that do not have the attribute @LIT{age} +/// at all. +/// +/// @verbinclude aqlnull2 +/// +/// This behavior should always be taken into account when writing queries. +/// +/// @subsection AqlOperators Operators +/// +/// AQL supports a number of operators that can be used in expressions. +/// There are comparison, logical, arithmetic, and the ternary operator. +/// +/// @subsubsection AqlOperatorsComparison Comparison operators +/// +/// Comparison (or relational) operators compare two operands. They can be used +/// with any input data types, and will return a boolean result value. +/// +/// The following comparison operators are supported: +/// +/// - @LIT{==} equality +/// - @LIT{!=} inequality +/// - @LIT{<} less than +/// - @LIT{<=} less or equal +/// - @LIT{>} greater than +/// - @LIT{>=} greater or equal +/// - @LIT{in} test if a value is contained in a list +/// +/// The @LIT{in} operator expects the second operand to be of type list. All +/// other operators accept any data types for the first and second operands. +/// +/// Each of the comparison operators returns a boolean value if the comparison +/// can be evaluated and returns @LIT{true} if the comparison evaluates to true, +/// and @LIT{false} otherwise. +/// /// @subsubsection AqlOperatorsLogical Logical operators /// +/// Logical operators combine two boolean operands in a logical operation and +/// return a boolean result value. +/// /// The following logical operators are supported: /// /// - @LIT{&&} logical and operator @@ -379,6 +447,10 @@ /// /// @subsubsection AqlOperatorsArithmetic Arithmetic operators /// +/// Arithmetic operators perform an arithmetic operation on two numeric operands. The +/// result of an arithmetic operation is again a numeric value. +/// operators are supported: +/// /// AQL supports the following arithmetic operators: /// /// - @LIT{+} addition @@ -418,7 +490,7 @@ /// - @LIT{&&} logical and /// - @LIT{==}, @LIT{!=} equality and inequality /// - @LIT{in} in operator -/// - @LIT{<}, @LIT{<=}, @LIT{>=}, @LIT{>} less than, less equal, +/// - @LIT{<}, @LIT{<=}, @LIT{>=}, @LIT{>} less than, less equal, /// greater equal, greater than /// - @LIT{+}, @LIT{-} addition, subtraction /// - @LIT{*}, @LIT{/}, @LIT{%} multiplication, division, modulus @@ -433,28 +505,306 @@ /// /// @subsection AqlFunctions Functions /// -/// TODO +/// 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: /// -/// @subsection AqlTypeCasting Type casting +/// @verbinclude aqlfunctionsyntax /// -/// TODO +/// @LIT{FUNCTIONNAME} is the name of the function to be called, and @LIT{arguments} +/// 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. Function names are case-sensitive. +/// Currently, all functions in AQL have upper-cased names. +/// +/// @subsubsection AqlFunctionsCasting Type cast functions +/// +/// 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. +/// +/// 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. The following type cast functions are +/// available: +/// +/// - @LIT{TONULL}: takes an input operand of any type and returns a @LIT{null} value +/// - @LIT{TOBOOL}: takes an input operand of any type and converts it into the appropriate +/// boolean value +/// - @LIT{TONUMBER}: takes an input operand of any type and converts it into +/// a numeric value +/// - @LIT{TOSTRING}: takes an input operand of any type and converts it into a string +/// value +/// +/// Each of the above functions takes an operand of any data type and returns a result +/// value of the requested type. +/// +/// @subsubsection AqlFunctionsChecking Type check functions +/// +/// AQL also offers functions to check the data type of a value at runtime. The +/// following type check functions are available: +/// +/// - @LIT{ISNULL}: checks whether the argument is a @LIT{null} value +/// - @LIT{ISBOOL}: checks whether the argument is a boolean value +/// - @LIT{ISNUMBER}: checks whether the argument is a numeric value +/// - @LIT{ISSTRING}: checks whether the argument is a string value +/// - @LIT{ISLIST}: checks whether the argument is a list value +/// - @LIT{ISDOCUMENT}: checks whether the argument is a document value +/// +/// Each of the above functions accepts an operand of any type and returns a boolean +/// result value. +/// +/// @subsubsection AqlFunctionsNumeric Numeric functions +/// +/// AQL offers some numeric functions for calculations. The following functions are +/// supported: +/// +/// - @LIT{FLOOR}: returns the integer closest but not greater to the specified value +/// - @LIT{CEIL}: returns the integer closest but not less than the specified value +/// - @LIT{ROUND}: returns the integer closest to the specified value +/// - @LIT{ABS}: returns the absolute value +/// - @LIT{RAND}: returns a random number between 0 and 1 +/// +/// @subsubsection AqlFunctionsString String functions +/// +/// AQL offers the following string-related functions: +/// +/// - @LIT{CONCAT}: concatenate the strings passed as arguments and return the result +/// string +/// +/// @subsubsection AqlFunctionsList List functions +/// +/// AQL supports the following functions to operate on list values: +/// +/// - @LIT{LENGTH}: returns the length (number of elements) of a list +/// - @LIT{MIN}: returns the smallest element of a list +/// - @LIT{MAX}: returns the greatest element of a list +/// +/// Apart from these functions, AQL also offers several language constructs (e.g. +/// @LIT{FOR}, @LIT{SORT}, @LIT{LIMT}, @LIT{COLLECT}) to operate on lists. /// /// @section AqlOperations High-level operations /// -/// @subsection AqlOperationFor For +/// @subsection AqlOperationFor FOR /// -/// @subsection AqlOperationReturn Return +/// The @LIT{FOR} keyword can be to iterate over all elements of a list. +/// The general syntax is: +/// +/// @verbinclude aqlforsyntax /// -/// @subsection AqlOperationFilter Filter +/// Each list element returned by @LIT{expression} is visited exactly once. It is +/// required that @LIT{expression} 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 @LIT{variable-name}. /// -/// @subsection AqlOperationSort Sort +/// @verbinclude aqlfor /// -/// @subsection AqlOperationLimit Limit +/// This will iterate over all elements from the list @LIT{users} (note: this list +/// consists of all documents from the collection named "users" in this case) and +/// make the current list element available in variable @LIT{u}. @LIT{u} is not modified +/// in this example but simply pushed into the result using the @LIT{RETURN} keyword. /// -/// @subsection AqlOperationLet Let +/// 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 @LIT{SORT} +/// statement. /// -/// @subsection AqlOperationCollect Collect +/// The variable introduced by @LIT{FOR} is available until the scope the @LIT{FOR} is +/// placed in is closed. /// +/// Another example that uses a statically declared list of values to iterate over: +/// +/// @verbinclude aqlforstatic +/// +/// Nesting of multiple @LIT{FOR} statements is allowed, too. When @LIT{FOR} statements +/// are nested, a cross product of the list elements returned by the individual @LIT{FOR} +/// statements will be created. +/// +/// @verbinclude aqlfornested +/// +/// In this example, there are two list iterations: an outer iteration +/// over the list @LIT{users} plus an inner iteration over the list @LIT{locations}. +/// The inner list is traversed as many times as there are elements in the outer +/// list. +/// For each iteration, the current values of @LIT{users} and @LIT{locations} are +/// made available for further processing in the variable @LIT{u} and @LIT{l}. +/// +/// @subsection AqlOperationReturn RETURN +/// +/// The @LIT{RETURN} statement can (and must) be used to produce the result of a query. +/// It is mandatory to specify a @LIT{RETURN} statement at the end of each block in a query, +/// otherwise the query result would be undefined. +/// +/// The general syntax for @LIT{return} is: +/// +/// @verbinclude aqlreturnsyntax +/// +/// The @LIT{expression} returned by @LIT{RETURN} is produced for each iteration the @LIT{RETURN} +/// statement is placed in. That means the result of a @LIT{RETURN} 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: +/// +/// @verbinclude aqlreturn +/// +/// As @LIT{RETURN} allows specifying an expression, arbitrary computations can be performed to +/// calculate the result elements. Any of the variables valid in the scope the @LIT{RETURN} is +/// placed in can be used for the computations. +/// +/// Note: return will close the current scope and eliminate all local variables in it. +/// +/// @subsection AqlOperationFilter FILTER +/// +/// The @LIT{FILTER} statement can be used to restrict the results to elements that match an +/// arbitrary logical condition. +/// The general syntax is: +/// +/// @verbinclude aqlfiltersyntax +/// +/// @LIT{condition} must be a condition that evaluates to either @LIT{false} or @LIT{true}. 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. +/// +/// @verbinclude aqlfilter +/// +/// In the above example, all list elements from @LIT{users} will be included that have an +/// attribute @LIT{active} with value @LIT{true} and that have an attribute @LIT{age} with a +/// value less than @LIT{39}. All other elements from @LIT{users} will be skipped and not +/// be included the result produced by @LIT{RETURN}. +/// +/// It is allowed to specifiy multiple @LIT{FILTER} statements in a query, and even in the +/// same block. If multiple @LIT{FILTER} statements are used, their results will be combined +/// with a logical and, meaning all filter conditions must be true to include an element. +/// +/// @verbinclude aqlfiltermultiple +/// +/// @subsection AqlOperationSort SORT +/// +/// The @LIT{SORT} statement will force a sort of the list of already produced intermediate +/// results in the current block. @LIT{SORT} allows specifying one or multiple sort criteria and +/// directions. +/// The general syntax is: +/// +/// @verbinclude aqlsortsyntax +/// +/// Specifiyng the @LIT{direction} is optional. The default (implict) direction for +/// a sort is the ascending order. To explicitly specify the sort direction, the keywords +/// @LIT{ASC} (ascending) and @LIT{DESC} can be used. Multiple sort criteria can be +/// separated using commas. +/// +/// Note: when iterating over collection-based lists, the order of documents is always +/// undefined unless an explicit sort order is defined using @LIT{SORT}. +/// +/// @verbinclude aqlsort +/// +/// @subsection AqlOperationLimit LIMIT +/// +/// The @LIT{LIMIT} 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 @LIT{LIMIT} are followed: +/// +/// @verbinclude aqllimitsyntax +/// +/// The first form allows specifying only the @LIT{count} value whereas the second form +/// allows specifying both @LIT{offset} and @LIT{count}. The first form is identical using +/// the second form with an @LIT{offset} value of @LIT{0}. +/// +/// The @LIT{offset} value specifies how many elements from the result shall be discarded. +/// It must be 0 or greater. The @LIT{count} value specifies how many elements should be +/// at most included in the result. +/// +/// @verbinclude aqllimit +/// +/// @subsection AqlOperationLet LET +/// +/// The @LIT{LET} statement can be used to assign an arbitrary value to a variable. +/// The variable is then introduced in the scope the @LIT{LET} statement is placed in. +/// The general syntax is: +/// +/// @verbinclude aqlletsyntax +/// +/// @LIT{LET} statements are mostly used to declare complex computations and to avoid +/// repeated computations of the same value at multiple parts of a query. +/// +/// @verbinclude aqllet +/// +/// In the above example, the computation of the number of recommendations is factored +/// out using a @LIT{LET} statement, thus avoiding computing the value twice in the +/// @LIT{RETURN} statement. +/// +/// Another use case for @LIT{LET} is to declare a complex computation in a subquery, +/// making the whole query more readable. +/// +/// @verbinclude aqllet2 +/// +/// @subsection AqlOperationCollect COLLECT +/// +/// The @LIT{COLLECT} keyword can be used to group a list by one or multiple +/// group criteria. +/// The two general syntaxes for @LIT{COLLECT} are: +/// +/// @verbinclude aqlcollectsyntax +/// +/// The first form only groups the result by the defined group criteria defined +/// by @LIT{expression}. In order to further process the results produced by +/// @LIT{COLLECT}, a new variable (specified by @LIT{variable-name} is introduced. +/// This variable contains the group value. +/// +/// The second form does the same as the first form, but additionally introduces +/// a variable (specified by @LIT{groups}) that contains all elements that fell into +/// the group. Specifying the @LIT{INTO} clause is optional- +/// +/// @verbinclude aqlcollect +/// +/// In the above example, the list of @LIT{users} will be grouped by the attribute +/// @LIT{city}. The result is a new list of documents, with one element per distinct +/// @LIT{city} value. The elements from the original list (here: @LIT{users}) per city +/// are made available in the variable @LIT{g}. This is due to the @LIT{INTO} clause. +/// +/// @LIT{COLLECT} also allows specifying multiple group criteria. Individual group +/// criteria can be separated by commas. +/// +/// @verbinclude aqlcollect2 +/// +/// In the above example, the list of @LIT{users} 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. +/// +/// Note: the @LIT{COLLECT} statement eliminates all local variables in the current +/// scope. After @LIT{COLLECT} only the variables introduced by @LIT{COLLECT} itself +/// are available. +/// +/// @section AqlAdvanced Advanced features +/// +/// @subsection AqlSubqueries Subqueries +/// +/// 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). +/// +/// @verbinclude aqlsubquery +/// +/// @subsection AqlExpansion Variable expansion +/// +/// In order to access a named attribute from all elements in a list easily, +/// AQL offers the shortcut operator @LIT{[*]} for variable expansion. +/// +/// Using the @LIT{[*]} 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 @LIT{[*]} operator is again a list. +/// +/// @verbinclude aqlexpansion +/// +/// In the above example, the attribute @LIT{name} is accessed for each element +/// in the list @LIT{u.friends}. The result is a flat list of friend names, made +/// available as the attribute @LIT{friendNames}. //////////////////////////////////////////////////////////////////////////////// // Local Variables: diff --git a/RestServer/ref-manual.dox b/RestServer/ref-manual.dox index 2696bd58a3..2104e87120 100644 --- a/RestServer/ref-manual.dox +++ b/RestServer/ref-manual.dox @@ -61,6 +61,8 @@ /// /// /// +///