diff --git a/Documentation/Books/Users/Aql/Invoke.mdpp b/Documentation/Books/Users/Aql/Invoke.mdpp index 92bf54032f..4d1ab3bf9b 100644 --- a/Documentation/Books/Users/Aql/Invoke.mdpp +++ b/Documentation/Books/Users/Aql/Invoke.mdpp @@ -10,31 +10,36 @@ of the *db* object. This will run the specified query in the context of the curr selected database and return the query results in a cursor. The results of the cursor can be printed using its *toArray* method: - arangosh> db._query("FOR my IN mycollection RETURN my._key").toArray(); + @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 To pass bind parameters into a query, they can be specified as second argument to the *_query* method: - arangosh> db._query("FOR c IN @@collection FILTER c._key == @key RETURN c._key", { - "@collection": "mycollection", - "key": "test1" + @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 Data-modifying AQL queries do not return a result, so the *toArray* method will always return an empty array. To retrieve statistics for a data-modification query, use the *getExtra* method: - arangosh> db._query("FOR i IN 1..100 INSERT { _key: CONCAT('test', TO_STRING(i)) } INTO mycollection").getExtra(); - { - "stats" : { - "writesExecuted" : 100, - "writesIgnored" : 0, - "scannedFull" : 0, - "scannedIndex" : 0, - "filtered" : 0 - }, - "warnings" : [ ] - } + @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 below. @@ -43,28 +48,44 @@ 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: - arangosh> stmt = db._createStatement( { "query": "FOR i IN [ 1, 2 ] RETURN i * 2" } ); - [object ArangoQueryCursor] + @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: - arangosh> c = stmt.execute(); - [object ArangoQueryCursor] + @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 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 *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. - arangosh> c.toArray(); - [2, 4] + @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: - arangosh> while (c.hasNext()) { require("internal").print(c.next()); } - 2 - 4 + @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 @@ -76,48 +97,74 @@ backwards iteration or random access to elements in a cursor. To execute an AQL query using bind parameters, you need to create a statement first and then bind the parameters to it before execution: - arangosh> stmt = db._createStatement( { "query": "FOR i IN [ @one, @two ] RETURN i * 2" } ); - [object ArangoStatement] - arangosh> stmt.bind("one", 1); - arangosh> stmt.bind("two", 2); - arangosh> c = stmt.execute(); - [object ArangoQueryCursor] + @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.: - arangosh> c.toArray(); - [2, 4] + @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 - arangosh> while (c.hasNext()) { require("internal").print(c.next()); } - 2 - 4 + @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: - arangosh> stmt = db._createStatement( { - "query": "FOR i IN [ @one, @two ] RETURN i * 2", - "bindVars": { - "one": 1, - "two": 2 - } + @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 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: - arangosh> stmt = db._createStatement( { "query": "FOR i IN [ 1, 2, 3, 4 ] RETURN i", "count": true } ); + @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: - arangosh> c = stmt.execute(); - [object ArangoQueryCursor] - arangosh> c.count(); - 4 + @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. @@ -143,17 +190,11 @@ A query that has been executed will always return execution statistics. Executio can be retrieved by calling `getExtra()` on the cursor. The statistics are returned in the return value's `stats` attribute: - arangosh> db._query("FOR i IN 1..100 INSERT { _key: CONCAT('test', TO_STRING(i)) } INTO mycollection").getExtra(); - { - "stats" : { - "writesExecuted" : 100, - "writesIgnored" : 0, - "scannedFull" : 0, - "scannedIndex" : 0, - "filtered" : 0 - }, - "warnings" : [ ] - } + @startDocuBlockInline 06_workWithAQL_statementsExtra + @EXAMPLE_ARANGOSH_OUTPUT{05_workWithAQL_statementsExtra} + db._query("FOR i IN 1..100 INSERT { _key: CONCAT('anothertest', TO_STRING(i)) } INTO mycollection").getExtra(); + @END_EXAMPLE_ARANGOSH_OUTPUT + @endDocuBlock 06_workWithAQL_statementsExtra The meaning of the statistics attributes is as follows: @@ -211,92 +252,33 @@ Each plan in the result is an object with the following attributes: Here is an example for retrieving the execution plan of a simple query: -``` -arangosh> var stmt = db._createStatement("FOR user IN _users RETURN user"); -arangosh> stmt.explain(); -{ - "plan" : { - "nodes" : [ - { - "type" : "SingletonNode", - "dependencies" : [ ], - "id" : 1, - "estimatedCost" : 1 - }, - { - "type" : "EnumerateCollectionNode", - "dependencies" : [ - 1 - ], - "id" : 2, - "estimatedCost" : 1, - "database" : "_system", - "collection" : "_users", - "outVariable" : { - "id" : 0, - "name" : "user" - } - }, - { - "type" : "ReturnNode", - "dependencies" : [ - 2 - ], - "id" : 3, - "estimatedCost" : 1, - "inVariable" : { - "id" : 0, - "name" : "user" - } - } - ], - "rules" : [ ], - "collections" : [ - { - "name" : "_users", - "type" : "read" - } - ], - "variables" : [ - { - "id" : 0, - "name" : "user" - } - ], - "estimatedCost" : 1 - }, - "warnings" : [ ] -} -``` + @startDocuBlockInline 07_workWithAQL_statementsExplain + @EXAMPLE_ARANGOSH_OUTPUT{07_workWithAQL_statementsExplain} + var stmt = db._createStatement("FOR user IN _users RETURN user"); + stmt.explain(); + @END_EXAMPLE_ARANGOSH_OUTPUT + @endDocuBlock 07_workWithAQL_statementsExplain As the output of `explain` is very detailed, it is recommended to use some scripting to make the output less verbose: -``` -arangosh> formatPlan = function (plan) { return { estimatedCost: plan.estimatedCost, nodes: plan.nodes.map(function(node) { return node.type; }) }; }; -arangosh> var stmt = db._createStatement("FOR user IN _users RETURN user"); -arangosh> formatPlan(stmt.explain().plan); -{ - "cost" : 1, - "nodes" : [ - "SingletonNode", - "EnumerateCollectionNode", - "ReturnNode" - ] -} -``` + @startDocuBlockInline 08_workWithAQL_statementsPlans + @EXAMPLE_ARANGOSH_OUTPUT{08_workWithAQL_statementsPlans} + var formatPlan = function (plan) { return { estimatedCost: plan.estimatedCost, nodes: plan.nodes.map(function(node) { return node.type; }) }; }; + formatPlan(stmt.explain().plan); + @END_EXAMPLE_ARANGOSH_OUTPUT + @endDocuBlock 08_workWithAQL_statementsPlans If a query contains bind parameters, they must be added to the statement **before** `explain` is called: -``` -arangosh> var stmt = db._createStatement("FOR doc IN @@collection FILTER doc.user == @user RETURN doc"); -arangosh> stmt.bind({ "@collection" : "_users", "user" : "root" }); -arangosh> stmt.explain(); -{ - ... -} -``` + @startDocuBlockInline 09_workWithAQL_statementsPlansBind + @EXAMPLE_ARANGOSH_OUTPUT{09_workWithAQL_statementsPlansBind} + var stmt = db._createStatement("FOR doc IN @@collection FILTER doc.user == @user RETURN doc"); + stmt.bind({ "@collection" : "_users", "user" : "root" }); + stmt.explain(); + @END_EXAMPLE_ARANGOSH_OUTPUT + @endDocuBlock 09_workWithAQL_statementsPlansBind In some cases the AQL optimizer creates multiple plans for a single query. By default only the plan with the lowest total estimated cost is kept, and the other plans are @@ -305,39 +287,21 @@ with the option `allPlans` set to `true`. In the following example, the optimizer has created two plans: -``` -arangosh> var stmt = db._createStatement("FOR user IN _users FILTER user.user == 'root' RETURN user"); -arangosh> stmt.explain({ allPlans: true }).plans.length; -2 -``` + @startDocuBlockInline 10_workWithAQL_statementsPlansOptimizer0 + @EXAMPLE_ARANGOSH_OUTPUT{10_workWithAQL_statementsPlansOptimizer0} + var stmt = db._createStatement("FOR user IN _users FILTER user.user == 'root' RETURN user"); + stmt.explain({ allPlans: true }).plans.length; + @END_EXAMPLE_ARANGOSH_OUTPUT + @endDocuBlock 10_workWithAQL_statementsPlansOptimizer0 To see a slightly more compact version of the plan, the following transformation can be applied: -``` -arangosh> stmt.explain({ allPlans: true }).plans.map(function(plan) { return formatPlan(plan); }); -[ - { - "cost" : 0.21, - "nodes" : [ - "SingletonNode", - "IndexRangeNode", - "CalculationNode", - "FilterNode", - "ReturnNode" - ] - }, - { - "cost" : 0.21, - "nodes" : [ - "SingletonNode", - "EnumerateCollectionNode", - "CalculationNode", - "FilterNode", - "ReturnNode" - ] - } -] -``` + @startDocuBlockInline 10_workWithAQL_statementsPlansOptimizer1 + @EXAMPLE_ARANGOSH_OUTPUT{10_workWithAQL_statementsPlansOptimizer1} + ~var stmt = db._createStatement("FOR user IN _users FILTER user.user == 'root' RETURN user"); + stmt.explain({ allPlans: true }).plans.map(function(plan) { return formatPlan(plan); }); + @END_EXAMPLE_ARANGOSH_OUTPUT + @endDocuBlock 10_workWithAQL_statementsPlansOptimizer1 `explain` will also accept the following additional options: - *maxPlans*: limits the maximum number of plans that are created by the AQL query optimizer @@ -348,18 +312,23 @@ arangosh> stmt.explain({ allPlans: true }).plans.map(function(plan) { return for The following example disables all optimizer rules but `remove-redundant-calculations`: -``` -arangosh> stmt.explain({ optimizer: { rules: [ "-all", "+remove-redundant-calculations" ] } }); -``` + @startDocuBlockInline 10_workWithAQL_statementsPlansOptimizer2 + @EXAMPLE_ARANGOSH_OUTPUT{10_workWithAQL_statementsPlansOptimizer2} + ~var stmt = db._createStatement("FOR user IN _users FILTER user.user == 'root' RETURN user"); + stmt.explain({ optimizer: { rules: [ "-all", "+remove-redundant-calculations" ] } }); + @END_EXAMPLE_ARANGOSH_OUTPUT + @endDocuBlock 10_workWithAQL_statementsPlansOptimizer2 The contents of an execution plan are meant to be machine-readable. To get a human-readable version of a query's execution plan, the following commnands can be used: -```js -arangosh> var query = "FOR doc IN collection FILTER doc.value > 42 RETURN doc"; -arangosh> require("org/arangodb/aql/explainer").explain(query); -``` + @startDocuBlockInline 10_workWithAQL_statementsPlansOptimizer3 + @EXAMPLE_ARANGOSH_OUTPUT{10_workWithAQL_statementsPlansOptimizer3} + var query = "FOR doc IN mycollection FILTER doc.value > 42 RETURN doc"; + require("org/arangodb/aql/explainer").explain(query, {colors:false}); + @END_EXAMPLE_ARANGOSH_OUTPUT + @endDocuBlock 10_workWithAQL_statementsPlansOptimizer3 The above command prints the query's execution plan in the ArangoShell directly, focusing on the most important information. @@ -380,17 +349,11 @@ Addtionally, the internal representation of the query, the query's abstract synt be returned in the `ast` attribute of the result. Please note that the abstract syntax tree will be returned without any optimizations applied to it. -``` -arangosh> var stmt = db._createStatement("FOR doc IN @@collection FILTER doc.foo == @bar RETURN doc"); -arangosh> stmt.parse(); -{ - "bindVars" : [ - "bar", - "@collection" - ], - "collections" : [ ], - "ast" : [ - ... - ] -} -``` + @startDocuBlockInline 11_workWithAQL_parseQueries + @EXAMPLE_ARANGOSH_OUTPUT{11_workWithAQL_parseQueries} + var stmt = db._createStatement("FOR doc IN @@collection FILTER doc.foo == @bar RETURN doc"); + stmt.parse(); + ~addIgnoreCollection("mycollection") + ~db._drop("mycollection") + @END_EXAMPLE_ARANGOSH_OUTPUT + @endDocuBlock 11_workWithAQL_parseQueries diff --git a/Documentation/Books/Users/FirstSteps/CollectionsAndDocuments.mdpp b/Documentation/Books/Users/FirstSteps/CollectionsAndDocuments.mdpp index 55214ada4b..1402aac3a8 100644 --- a/Documentation/Books/Users/FirstSteps/CollectionsAndDocuments.mdpp +++ b/Documentation/Books/Users/FirstSteps/CollectionsAndDocuments.mdpp @@ -28,12 +28,12 @@ embedded version in the browser. Using the command-line tool has the advantage that you can use autocompletion. unix> arangosh --server.password "" - _ - __ _ _ __ __ _ _ __ __ _ ___ ___| |__ + _ + __ _ _ __ __ _ _ __ __ _ ___ ___| |__ / _` | '__/ _` | '_ \ / _` |/ _ \/ __| '_ \ | (_| | | | (_| | | | | (_| | (_) \__ \ | | | \__,_|_| \__,_|_| |_|\__, |\___/|___/_| |_| - |___/ + |___/ Welcome to arangosh 2.x.y. Copyright (c) 2012 triAGENS GmbH. Using Google V8 4.1.0.27 JavaScript engine.