1
0
Fork 0

Documentation: Aql update

This commit is contained in:
jmvan 2016-01-27 19:55:34 +01:00
parent 7a11220acc
commit adc5702422
6 changed files with 252 additions and 241 deletions

View File

@ -1,6 +1,5 @@
!CHAPTER Advanced features
* [Combining queries](CombiningQueries.md)
* [Array operators](ArrayOperators.md)

View File

@ -0,0 +1,236 @@
!CHAPTER Executing queries from Arangosh
Within the ArangoDB shell, the *_query* and *_createStatement* methods of the *db* object can be used to execute AQL queries.
This chapter also describes how to use data binding, counting, statistics and cursors.
!SUBSECTION with db._query
One can execute queries with the *_query* method of the *db* object.
This will run the specified query in the context of the currently
selected database and return the query results in a cursor. The results of the cursor
can be printed using its *toArray* method:
@startDocuBlockInline 01_workWithAQL_all
@EXAMPLE_ARANGOSH_OUTPUT{01_workWithAQL_all}
~addIgnoreCollection("mycollection")
db._create("mycollection")
db.mycollection.save({ _key: "testKey", Hello : "World" })
db._query('FOR my IN mycollection RETURN my._key').toArray()
@END_EXAMPLE_ARANGOSH_OUTPUT
@endDocuBlock 01_workWithAQL_all
!SUBSUBSECTION db._query Bind parameters
To pass bind parameters into a query, they can be specified as second argument to the
*_query* method:
@startDocuBlockInline 02_workWithAQL_bindValues
@EXAMPLE_ARANGOSH_OUTPUT{02_workWithAQL_bindValues}
|db._query(
| 'FOR c IN @@collection FILTER c._key == @key RETURN c._key', {
| '@collection': 'mycollection',
| 'key': 'testKey'
}).toArray();
@END_EXAMPLE_ARANGOSH_OUTPUT
@endDocuBlock 02_workWithAQL_bindValues
!SUBSUBSECTION ES6 template strings
It is also possible to use ES6 template strings for generating AQL queries. There is
a template string generator function named *aqlQuery*:
@startDocuBlockInline 02_workWithAQL_aqlQuery
@EXAMPLE_ARANGOSH_OUTPUT{02_workWithAQL_aqlQuery}
var key = 'testKey';
|db._query(
| aqlQuery`FOR c IN mycollection FILTER c._key == ${key} RETURN c._key`
).toArray();
@END_EXAMPLE_ARANGOSH_OUTPUT
@endDocuBlock 02_workWithAQL_aqlQuery
Arbitrary JavaScript expressions can be used in queries that are generated with the
*aqlQuery* template string generator. Collection objects are handled automatically:
@startDocuBlockInline 02_workWithAQL_aqlCollectionQuery
@EXAMPLE_ARANGOSH_OUTPUT{02_workWithAQL_aqlCollectionQuery}
var key = 'testKey';
|db._query(aqlQuery`FOR doc IN ${ db.mycollection } RETURN doc`
).toArray();
@END_EXAMPLE_ARANGOSH_OUTPUT
@endDocuBlock 02_workWithAQL_aqlCollectionQuery
Note: data-modification AQL queries normally do not return a result (unless the AQL query
contains an extra *RETURN* statement). When not using a *RETURN* statement in the query, the
*toArray* method will return an empty array.
!SUBSUBSECTION Statistics and extra Information
It is always possible to retrieve statistics for a query with the *getExtra* method:
@startDocuBlockInline 03_workWithAQL_getExtra
@EXAMPLE_ARANGOSH_OUTPUT{03_workWithAQL_getExtra}
|db._query(`FOR i IN 1..100
| INSERT { _key: CONCAT('test', TO_STRING(i)) }
| INTO mycollection`
).getExtra();
@END_EXAMPLE_ARANGOSH_OUTPUT
@endDocuBlock 03_workWithAQL_getExtra
The meaning of the statistics values is described in [Execution statistics](QueryStatistics.md).
You also will find warnings in here; If you're designing queries on the shell be sure to also look at it.
!SUBSECTION with _createStatement (ArangoStatement)
The *_query* method is a shorthand for creating an ArangoStatement object,
executing it and iterating over the resulting cursor. If more control over the
result set iteration is needed, it is recommended to first create an
ArangoStatement object as follows:
@startDocuBlockInline 04_workWithAQL_statements1
@EXAMPLE_ARANGOSH_OUTPUT{04_workWithAQL_statements1}
|stmt = db._createStatement( {
"query": "FOR i IN [ 1, 2 ] RETURN i * 2" } );
@END_EXAMPLE_ARANGOSH_OUTPUT
@endDocuBlock 04_workWithAQL_statements1
To execute the query, use the *execute* method of the statement:
@startDocuBlockInline 05_workWithAQL_statements2
@EXAMPLE_ARANGOSH_OUTPUT{05_workWithAQL_statements2}
~var stmt = db._createStatement( { "query": "FOR i IN [ 1, 2 ] RETURN i * 2" } );
c = stmt.execute();
@END_EXAMPLE_ARANGOSH_OUTPUT
@endDocuBlock 05_workWithAQL_statements2
!SUBSUBSECTION Cursors
Once the query executed the query results are available in a cursor.
The cursor can return all its results at once using the *toArray* method.
This is a short-cut that you can use if you want to access the full result
set without iterating over it yourself.
@startDocuBlockInline 05_workWithAQL_statements3
@EXAMPLE_ARANGOSH_OUTPUT{05_workWithAQL_statements3}
~var stmt = db._createStatement( { "query": "FOR i IN [ 1, 2 ] RETURN i * 2" } );
~var c = stmt.execute();
c.toArray();
@END_EXAMPLE_ARANGOSH_OUTPUT
@endDocuBlock 05_workWithAQL_statements3
Cursors can also be used to iterate over the result set document-by-document.
To do so, use the *hasNext* and *next* methods of the cursor:
@startDocuBlockInline 05_workWithAQL_statements4
@EXAMPLE_ARANGOSH_OUTPUT{05_workWithAQL_statements4}
~var stmt = db._createStatement( { "query": "FOR i IN [ 1, 2 ] RETURN i * 2" } );
~var c = stmt.execute();
while (c.hasNext()) { require("internal").print(c.next()); }
@END_EXAMPLE_ARANGOSH_OUTPUT
@endDocuBlock 05_workWithAQL_statements4
Please note that you can iterate over the results of a cursor only once, and that
the cursor will be empty when you have fully iterated over it. To iterate over
the results again, the query needs to be re-executed.
Additionally, the iteration can be done in a forward-only fashion. There is no
backwards iteration or random access to elements in a cursor.
!SUBSUBSECTION ArangoStatement parameters binding
To execute an AQL query using bind parameters, you need to create a statement first
and then bind the parameters to it before execution:
@startDocuBlockInline 05_workWithAQL_statements5
@EXAMPLE_ARANGOSH_OUTPUT{05_workWithAQL_statements5}
|var stmt = db._createStatement( {
"query": "FOR i IN [ @one, @two ] RETURN i * 2" } );
stmt.bind("one", 1);
stmt.bind("two", 2);
c = stmt.execute();
@END_EXAMPLE_ARANGOSH_OUTPUT
@endDocuBlock 05_workWithAQL_statements5
The cursor results can then be dumped or iterated over as usual, e.g.:
@startDocuBlockInline 05_workWithAQL_statements6
@EXAMPLE_ARANGOSH_OUTPUT{05_workWithAQL_statements6}
~var stmt = db._createStatement( { "query": "FOR i IN [ @one, @two ] RETURN i * 2" } );
~stmt.bind("one", 1);
~stmt.bind("two", 2);
~var c = stmt.execute();
c.toArray();
@END_EXAMPLE_ARANGOSH_OUTPUT
@endDocuBlock 05_workWithAQL_statements6
or
@startDocuBlockInline 05_workWithAQL_statements7
@EXAMPLE_ARANGOSH_OUTPUT{05_workWithAQL_statements7}
~var stmt = db._createStatement( { "query": "FOR i IN [ @one, @two ] RETURN i * 2" } );
~stmt.bind("one", 1);
~stmt.bind("two", 2);
~var c = stmt.execute();
while (c.hasNext()) { require("internal").print(c.next()); }
@END_EXAMPLE_ARANGOSH_OUTPUT
@endDocuBlock 05_workWithAQL_statements7
Please note that bind parameters can also be passed into the *_createStatement* method directly,
making it a bit more convenient:
@startDocuBlockInline 05_workWithAQL_statements8
@EXAMPLE_ARANGOSH_OUTPUT{05_workWithAQL_statements8}
|stmt = db._createStatement( {
| "query": "FOR i IN [ @one, @two ] RETURN i * 2",
| "bindVars": {
| "one": 1,
| "two": 2
| }
} );
@END_EXAMPLE_ARANGOSH_OUTPUT
@endDocuBlock 05_workWithAQL_statements8
!SUBSUBSECTION Counting with a cursor
Cursors also optionally provide the total number of results. By default, they do not.
To make the server return the total number of results, you may set the *count* attribute to
*true* when creating a statement:
@startDocuBlockInline 05_workWithAQL_statements9
@EXAMPLE_ARANGOSH_OUTPUT{05_workWithAQL_statements9}
|stmt = db._createStatement( {
| "query": "FOR i IN [ 1, 2, 3, 4 ] RETURN i",
"count": true } );
@END_EXAMPLE_ARANGOSH_OUTPUT
@endDocuBlock 05_workWithAQL_statements9
After executing this query, you can use the *count* method of the cursor to get the
number of total results from the result set:
@startDocuBlockInline 05_workWithAQL_statements10
@EXAMPLE_ARANGOSH_OUTPUT{05_workWithAQL_statements10}
~var stmt = db._createStatement( { "query": "FOR i IN [ 1, 2, 3, 4 ] RETURN i", "count": true } );
var c = stmt.execute();
c.count();
@END_EXAMPLE_ARANGOSH_OUTPUT
@endDocuBlock 05_workWithAQL_statements10
Please note that the *count* method returns nothing if you did not specify the *count*
attribute when creating the query.
This is intentional so that the server may apply optimizations when executing the query and
construct the result set incrementally. Incremental creation of the result sets
is no possible
if all of the results need to be shipped to the client anyway. Therefore, the client
has the choice to specify *count* and retrieve the total number of results for a query (and
disable potential incremental result set creation on the server), or to not retrieve the total
number of results and allow the server to apply optimizations.
Please note that at the moment the server will always create the full result set for each query so
specifying or omitting the *count* attribute currently does not have any impact on query execution.
This may change in the future. Future versions of ArangoDB may create result sets incrementally
on the server-side and may be able to apply optimizations if a result set is not fully fetched by
a client.

View File

@ -3,239 +3,10 @@
You can run AQL queries from your application via the HTTP REST API. The full
API description is available at [HTTP Interface for AQL Query Cursors](../HttpAqlQueryCursor/README.md).
You can also run AQL queries from arangosh.
The [ArangoDB Web Interface](../WebInterface/README.md) has a specific tab for AQL queries execution.
!SECTION Executing queries from Arangosh
You can run [AQL queries from the ArangoDB Shell](AqlWithArangosh.md) with the *_query* and *_createStatement* methods of the *db* object.
This chapter also describes how to use data binding, statistics, counting and cursors with arangosh.
!SUBSECTION with db._query
One can execute queries with the *_query* method of the *db* object.
This will run the specified query in the context of the currently
selected database and return the query results in a cursor. The results of the cursor
can be printed using its *toArray* method:
@startDocuBlockInline 01_workWithAQL_all
@EXAMPLE_ARANGOSH_OUTPUT{01_workWithAQL_all}
~addIgnoreCollection("mycollection")
db._create("mycollection")
db.mycollection.save({ _key: "testKey", Hello : "World" })
db._query('FOR my IN mycollection RETURN my._key').toArray()
@END_EXAMPLE_ARANGOSH_OUTPUT
@endDocuBlock 01_workWithAQL_all
!SUBSUBSECTION db._query Bind parameters
To pass bind parameters into a query, they can be specified as second argument to the
*_query* method:
@startDocuBlockInline 02_workWithAQL_bindValues
@EXAMPLE_ARANGOSH_OUTPUT{02_workWithAQL_bindValues}
|db._query(
| 'FOR c IN @@collection FILTER c._key == @key RETURN c._key', {
| '@collection': 'mycollection',
| 'key': 'testKey'
}).toArray();
@END_EXAMPLE_ARANGOSH_OUTPUT
@endDocuBlock 02_workWithAQL_bindValues
!SUBSUBSECTION ES6 template strings
It is also possible to use ES6 template strings for generating AQL queries. There is
a template string generator function named *aqlQuery*:
@startDocuBlockInline 02_workWithAQL_aqlQuery
@EXAMPLE_ARANGOSH_OUTPUT{02_workWithAQL_aqlQuery}
var key = 'testKey';
|db._query(
| aqlQuery`FOR c IN mycollection FILTER c._key == ${key} RETURN c._key`
).toArray();
@END_EXAMPLE_ARANGOSH_OUTPUT
@endDocuBlock 02_workWithAQL_aqlQuery
Arbitrary JavaScript expressions can be used in queries that are generated with the
*aqlQuery* template string generator. Collection objects are handled automatically:
@startDocuBlockInline 02_workWithAQL_aqlCollectionQuery
@EXAMPLE_ARANGOSH_OUTPUT{02_workWithAQL_aqlCollectionQuery}
var key = 'testKey';
|db._query(aqlQuery`FOR doc IN ${ db.mycollection } RETURN doc`
).toArray();
@END_EXAMPLE_ARANGOSH_OUTPUT
@endDocuBlock 02_workWithAQL_aqlCollectionQuery
Note: data-modification AQL queries normally do not return a result (unless the AQL query
contains an extra *RETURN* statement). When not using a *RETURN* statement in the query, the
*toArray* method will return an empty array.
!SUBSUBSECTION Statistics and extra Information
It is always possible to retrieve statistics for a query with the *getExtra* method:
@startDocuBlockInline 03_workWithAQL_getExtra
@EXAMPLE_ARANGOSH_OUTPUT{03_workWithAQL_getExtra}
|db._query(`FOR i IN 1..100
| INSERT { _key: CONCAT('test', TO_STRING(i)) }
| INTO mycollection`
).getExtra();
@END_EXAMPLE_ARANGOSH_OUTPUT
@endDocuBlock 03_workWithAQL_getExtra
The meaning of the statistics values is described in [Execution statistics](QueryStatistics.md).
You also will find warnings in here; If you're designing queries on the shell be shure to also look at it.
!SUBSECTION with _createStatement (ArangoStatement)
The *_query* method is a shorthand for creating an ArangoStatement object,
executing it and iterating over the resulting cursor. If more control over the
result set iteration is needed, it is recommended to first create an
ArangoStatement object as follows:
@startDocuBlockInline 04_workWithAQL_statements1
@EXAMPLE_ARANGOSH_OUTPUT{04_workWithAQL_statements1}
|stmt = db._createStatement( {
"query": "FOR i IN [ 1, 2 ] RETURN i * 2" } );
@END_EXAMPLE_ARANGOSH_OUTPUT
@endDocuBlock 04_workWithAQL_statements1
To execute the query, use the *execute* method of the statement:
@startDocuBlockInline 05_workWithAQL_statements2
@EXAMPLE_ARANGOSH_OUTPUT{05_workWithAQL_statements2}
~var stmt = db._createStatement( { "query": "FOR i IN [ 1, 2 ] RETURN i * 2" } );
c = stmt.execute();
@END_EXAMPLE_ARANGOSH_OUTPUT
@endDocuBlock 05_workWithAQL_statements2
!SUBSUBSECTION Cursors
Once the query executed the query results are available in a cursor.
The cursor can return all its results at once using the *toArray* method.
This is a short-cut that you can use if you want to access the full result
set without iterating over it yourself.
@startDocuBlockInline 05_workWithAQL_statements3
@EXAMPLE_ARANGOSH_OUTPUT{05_workWithAQL_statements3}
~var stmt = db._createStatement( { "query": "FOR i IN [ 1, 2 ] RETURN i * 2" } );
~var c = stmt.execute();
c.toArray();
@END_EXAMPLE_ARANGOSH_OUTPUT
@endDocuBlock 05_workWithAQL_statements3
Cursors can also be used to iterate over the result set document-by-document.
To do so, use the *hasNext* and *next* methods of the cursor:
@startDocuBlockInline 05_workWithAQL_statements4
@EXAMPLE_ARANGOSH_OUTPUT{05_workWithAQL_statements4}
~var stmt = db._createStatement( { "query": "FOR i IN [ 1, 2 ] RETURN i * 2" } );
~var c = stmt.execute();
while (c.hasNext()) { require("internal").print(c.next()); }
@END_EXAMPLE_ARANGOSH_OUTPUT
@endDocuBlock 05_workWithAQL_statements4
Please note that you can iterate over the results of a cursor only once, and that
the cursor will be empty when you have fully iterated over it. To iterate over
the results again, the query needs to be re-executed.
Additionally, the iteration can be done in a forward-only fashion. There is no
backwards iteration or random access to elements in a cursor.
!SUBSUBSECTION ArangoStatement parameters binding
To execute an AQL query using bind parameters, you need to create a statement first
and then bind the parameters to it before execution:
@startDocuBlockInline 05_workWithAQL_statements5
@EXAMPLE_ARANGOSH_OUTPUT{05_workWithAQL_statements5}
|var stmt = db._createStatement( {
"query": "FOR i IN [ @one, @two ] RETURN i * 2" } );
stmt.bind("one", 1);
stmt.bind("two", 2);
c = stmt.execute();
@END_EXAMPLE_ARANGOSH_OUTPUT
@endDocuBlock 05_workWithAQL_statements5
The cursor results can then be dumped or iterated over as usual, e.g.:
@startDocuBlockInline 05_workWithAQL_statements6
@EXAMPLE_ARANGOSH_OUTPUT{05_workWithAQL_statements6}
~var stmt = db._createStatement( { "query": "FOR i IN [ @one, @two ] RETURN i * 2" } );
~stmt.bind("one", 1);
~stmt.bind("two", 2);
~var c = stmt.execute();
c.toArray();
@END_EXAMPLE_ARANGOSH_OUTPUT
@endDocuBlock 05_workWithAQL_statements6
or
@startDocuBlockInline 05_workWithAQL_statements7
@EXAMPLE_ARANGOSH_OUTPUT{05_workWithAQL_statements7}
~var stmt = db._createStatement( { "query": "FOR i IN [ @one, @two ] RETURN i * 2" } );
~stmt.bind("one", 1);
~stmt.bind("two", 2);
~var c = stmt.execute();
while (c.hasNext()) { require("internal").print(c.next()); }
@END_EXAMPLE_ARANGOSH_OUTPUT
@endDocuBlock 05_workWithAQL_statements7
Please note that bind parameters can also be passed into the *_createStatement* method directly,
making it a bit more convenient:
@startDocuBlockInline 05_workWithAQL_statements8
@EXAMPLE_ARANGOSH_OUTPUT{05_workWithAQL_statements8}
|stmt = db._createStatement( {
| "query": "FOR i IN [ @one, @two ] RETURN i * 2",
| "bindVars": {
| "one": 1,
| "two": 2
| }
} );
@END_EXAMPLE_ARANGOSH_OUTPUT
@endDocuBlock 05_workWithAQL_statements8
!SUBSUBSECTION Counting with a cursor
Cursors also optionally provide the total number of results. By default, they do not.
To make the server return the total number of results, you may set the *count* attribute to
*true* when creating a statement:
@startDocuBlockInline 05_workWithAQL_statements9
@EXAMPLE_ARANGOSH_OUTPUT{05_workWithAQL_statements9}
|stmt = db._createStatement( {
| "query": "FOR i IN [ 1, 2, 3, 4 ] RETURN i",
"count": true } );
@END_EXAMPLE_ARANGOSH_OUTPUT
@endDocuBlock 05_workWithAQL_statements9
After executing this query, you can use the *count* method of the cursor to get the
number of total results from the result set:
@startDocuBlockInline 05_workWithAQL_statements10
@EXAMPLE_ARANGOSH_OUTPUT{05_workWithAQL_statements10}
~var stmt = db._createStatement( { "query": "FOR i IN [ 1, 2, 3, 4 ] RETURN i", "count": true } );
var c = stmt.execute();
c.count();
@END_EXAMPLE_ARANGOSH_OUTPUT
@endDocuBlock 05_workWithAQL_statements10
Please note that the *count* method returns nothing if you did not specify the *count*
attribute when creating the query.
This is intentional so that the server may apply optimizations when executing the query and
construct the result set incrementally. Incremental creation of the result sets
is no possible
if all of the results need to be shipped to the client anyway. Therefore, the client
has the choice to specify *count* and retrieve the total number of results for a query (and
disable potential incremental result set creation on the server), or to not retrieve the total
number of results and allow the server to apply optimizations.
Please note that at the moment the server will always create the full result set for each query so
specifying or omitting the *count* attribute currently does not have any impact on query execution.
This may change in the future. Future versions of ArangoDB may create result sets incrementally
on the server-side and may be able to apply optimizations if a result set is not fully fetched by
a client.

View File

@ -21,7 +21,7 @@ about the optimizer's view of the query.
!SUBSECTION Inspecting plans using the explain helper
The `explain` method of `ArangoStatement` as shown in the next chapters creates very verbose output.
You can work on the output programaticaly, or use this handsome tool that we created
You can work on the output programmatically, or use this handsome tool that we created
to generate a more human readable representation.
You may use it like this: (we disable syntax highlighting here)
@ -40,7 +40,7 @@ You may use it like this: (we disable syntax highlighting here)
!SUBSECTION Execution plans in detail
Lets have a look at the raw json output of the same execution plan
Let's have a look at the raw json output of the same execution plan
using the `explain` method of `ArangoStatement`:
@startDocuBlockInline AQLEXP_01_explainCreate
@ -50,7 +50,7 @@ using the `explain` method of `ArangoStatement`:
@END_EXAMPLE_ARANGOSH_OUTPUT
@endDocuBlock AQLEXP_01_explainCreate
The as you can see, result details are very verbose so we will not shown them in full in the next
As you can see, the result details are very verbose so we will not show them in full in the next
sections. Instead, lets take a closer look at the results step by step.
!SUBSUBSECTION Execution nodes

View File

@ -18,11 +18,6 @@ FOR u IN users
RETURN u
```
In the above example, all array elements from *users* will be included that have
an attribute *active* with value *true* and that have an attribute *age* with a
value less than *39* (including *null* ones). All other elements from *users*
will be skipped and not be included the result produced by *RETURN*.
It is allowed to specify multiple *FILTER* statements in a query, and even in
the same block. If multiple *FILTER* statements are used, their results will be
combined with a logical and, meaning all filter conditions must be true to
@ -35,3 +30,12 @@ FOR u IN users
RETURN u
```
In the above example, will be included in the result all array elements from *users* that have
an attribute *active* with value *true* and that have an attribute *age* with a
value less than *39* (including *null* ones). All other elements from *users*
will be skipped and not be included in the result produced by *RETURN*.
You may refer to the chapter [Accessing Data from Collections](../Aql/DocumentData.md) for
a description of the impact of non-existent or null attributes.

View File

@ -71,6 +71,7 @@
* [Limitations](Transactions/Limitations.md)
* [AQL](Aql/README.md)
* [How to invoke AQL](Aql/Invoke.md)
* [AQL with Arangosh](Aql/AqlWithArangosh.md)
* [Data modification queries](Aql/DataModification.md)
* [AQL Fundamentals](Aql/Fundamentals.md)
* [AQL Syntax](Aql/Syntax.md)