diff --git a/Documentation/Books/AQL/CommonErrors.mdpp b/Documentation/Books/AQL/CommonErrors.mdpp new file mode 100644 index 0000000000..15f3f1cb14 --- /dev/null +++ b/Documentation/Books/AQL/CommonErrors.mdpp @@ -0,0 +1 @@ +!CHAPTER Common Errors diff --git a/Documentation/Books/AQL/DataModification.mdpp b/Documentation/Books/AQL/DataModification.mdpp index 1f097227ef..67fe952664 100644 --- a/Documentation/Books/AQL/DataModification.mdpp +++ b/Documentation/Books/AQL/DataModification.mdpp @@ -8,7 +8,7 @@ AQL supports the following data-modification operations: - **REMOVE**: remove existing documents from a collection - **UPSERT**: conditionally insert or update documents in a collection -Those operations are detailed in the chapter [High Level Operations](Operations.md). +Those operations are detailed in the chapter [High Level Operations](Operations/README.md). !SUBSECTION Modifying a single document @@ -16,34 +16,49 @@ Those operations are detailed in the chapter [High Level Operations](Operations. Let's start with the basics: `INSERT`, `UPDATE` and `REMOVE` operations on single documents. Here is an example that insert a document in an existing collection *users*: - INSERT {firstName:'Anna', name:'Pavlova', profession:'artist'} IN users +```js +INSERT { firstName: "Anna", name: "Pavlova", profession: "artist" } IN users +``` You may provide a key for the new document; if not provided, ArangoDB will create one for you. - INSERT {_key:'GilbertoGil', firstName:'Gilberto', name:'Gil', city:'Fortalezza'} IN users +```js +INSERT { _key: "GilbertoGil", firstName: "Gilberto", name: "Gil", city: "Fortalezza" } IN users +``` As Arango is schema-free, attributes of the documents may vary: - INSERT {_key:'PhilCarpenter', firstName:'Phil', name:'Carpenter', middleName:'G.',status:'inactive', } IN users +```js +INSERT { _key: "PhilCarpenter", firstName: "Phil", name: "Carpenter", middleName: "G.", status: "inactive" } IN users +``` - INSERT {_key:'NatachaDeclerck', firstName:'Natacha', name:'Declerck', location:'Antwerp'} IN users +```js +INSERT { _key: "NatachaDeclerck", firstName: "Natacha", name: "Declerck", location: "Antwerp" } IN users +``` Update is quite simple. The following AQL statement will add or change the attributes status and location - UPDATE 'PhilCarpenter' WITH { status:'active', location:'Beijing' } IN users +```js +UPDATE "PhilCarpenter" WITH { status: "active", location: "Beijing" } IN users +``` Replace is an alternative to update where all attributes of the document are replaced. - REPLACE { _key: 'NatachaDeclerck', firstName:'Natacha', name:'Leclerc', status: 'active', level:'premium' } IN users +```js +REPLACE { _key: "NatachaDeclerck", firstName: "Natacha", name: "Leclerc", status: "active", level: "premium" } IN users +``` Removing a document if you know its key is simple as well : - REMOVE 'GilbertoGil' IN users +```js +REMOVE "GilbertoGil" IN users +``` or - REMOVE {_key:'GilbertoGil'} IN users - +```js +REMOVE { _key: "GilbertoGil" } IN users +``` !SUBSECTION Modifying multiple documents @@ -54,26 +69,30 @@ iterate over a given list of documents. They can optionally be combined with Let's start with an example that modifies existing documents in a collection *users* that match some condition: - FOR u IN users - FILTER u.status == 'not active' - UPDATE u WITH { status: 'inactive' } IN users - +```js +FOR u IN users + FILTER u.status == "not active" + UPDATE u WITH { status: "inactive" } IN users +``` Now, let's copy the contents of the collection *users* into the collection *backup*: - FOR u IN users - INSERT u IN backup +```js +FOR u IN users + INSERT u IN backup +``` As a final example, let's find some documents in collection *users* and remove them from collection *backup*. The link between the documents in both collections is established via the documents' keys: - FOR u IN users - FILTER u.status == 'deleted' - REMOVE u IN backup - +```js +FOR u IN users + FILTER u.status == "deleted" + REMOVE u IN backup +``` !SUBSECTION Returning documents @@ -81,19 +100,25 @@ Data-modification queries can optionally return documents. In order to reference the inserted, removed or modified documents in a `RETURN` statement, data-modification statements introduce the `OLD` and/or `NEW` pseudo-values: - FOR i IN 1..100 - INSERT { value: i } IN test - RETURN NEW +```js +FOR i IN 1..100 + INSERT { value: i } IN test + RETURN NEW +``` - FOR u IN users - FILTER u.status == 'deleted' - REMOVE u IN users - RETURN OLD +```js +FOR u IN users + FILTER u.status == "deleted" + REMOVE u IN users + RETURN OLD +``` - FOR u IN users - FILTER u.status == 'not active' - UPDATE u WITH { status: 'inactive' } IN users - RETURN NEW +```js +FOR u IN users + FILTER u.status == "not active" + UPDATE u WITH { status: "inactive" } IN users + RETURN NEW +``` `NEW` refers to the inserted or modified document revision, and `OLD` refers to the document revision before update or removal. `INSERT` statements can @@ -112,21 +137,23 @@ by queries. For example, the following query will return only the keys of the inserted documents: - FOR i IN 1..100 - INSERT { value: i } IN test - RETURN NEW._key - +```js +FOR i IN 1..100 + INSERT { value: i } IN test + RETURN NEW._key +``` !SUBSUBSECTION Using OLD and NEW in the same query For `UPDATE`, `REPLACE` and `UPSERT` statements, both `OLD` and `NEW` can be used to return the previous revision of a document together with the updated revision: - FOR u IN users - FILTER u.status == 'not active' - UPDATE u WITH { status: 'inactive' } IN users - RETURN { old: OLD, new: NEW } - +```js +FOR u IN users + FILTER u.status == "not active" + UPDATE u WITH { status: "inactive" } IN users + RETURN { old: OLD, new: NEW } +``` !SUBSUBSECTION Calculations with OLD or NEW @@ -137,18 +164,20 @@ updated, or a new document was inserted. It does so by checking the `OLD` variab after the `UPSERT` and using a `LET` statement to store a temporary string for the operation type: - UPSERT { name: 'test' } - INSERT { name: 'test' } - UPDATE { } IN users - LET opType = IS_NULL(old) ? 'insert' : 'update' - RETURN { _key: NEW._key, type: opType } - +```js +UPSERT { name: "test" } + INSERT { name: "test" } + UPDATE { } IN users +LET opType = IS_NULL(old) ? "insert" : "update" +RETURN { _key: NEW._key, type: opType } +``` !SUBSECTION Restrictions The name of the modified collection (*users* and *backup* in the above cases) must be known to the AQL executor at query-compile time and cannot change at -runtime. Using a bind parameter to specify the [collection name](../Glossary/README.md#collection-name) is allowed. +runtime. Using a bind parameter to specify the +[collection name](../Users/Appendix/Glossary.html#collection-name) is allowed. Data-modification queries are restricted to modifying data in a single collection per query. That means a data-modification query cannot modify diff --git a/Documentation/Books/AQL/Examples/CombiningGraphTraversals.mdpp b/Documentation/Books/AQL/Examples/CombiningGraphTraversals.mdpp index 0ec1027923..ec6904b3b3 100644 --- a/Documentation/Books/AQL/Examples/CombiningGraphTraversals.mdpp +++ b/Documentation/Books/AQL/Examples/CombiningGraphTraversals.mdpp @@ -1,9 +1,9 @@ !CHAPTER Combining Graph Traversals !SUBSECTION Finding the start vertex via a geo query -Our first example will locate the start vertex for a graph traversal via [a geo index](../IndexHandling/Geo.md). -We use [the city graph](../Graphs/README.md#the-city-graph) and its geo indices: +Our first example will locate the start vertex for a graph traversal via [a geo index](../../Users/Indexing/Geo.html). +We use [the city graph](../../Users/Graphs/index.html#the-city-graph) and its geo indices: -![Cities Example Graph](../Graphs/cities_graph.png) +![Cities Example Graph](../../Users/Graphs/cities_graph.png) @startDocuBlockInline COMBINING_GRAPH_01_create_graph diff --git a/Documentation/Books/AQL/Examples/Counting.mdpp b/Documentation/Books/AQL/Examples/Counting.mdpp index fa6d730bcf..746cd8b625 100644 --- a/Documentation/Books/AQL/Examples/Counting.mdpp +++ b/Documentation/Books/AQL/Examples/Counting.mdpp @@ -3,7 +3,7 @@ !SECTION Amount of documents in a collection To return the count of documents that currently exist in a collection, -you can call the [LENGTH() function](../Aql/ArrayFunctions.md#length): +you can call the [LENGTH() function](../Functions/Array.md#length): ``` RETURN LENGTH(collection) @@ -11,11 +11,13 @@ RETURN LENGTH(collection) This type of call is optimized since 2.8 (no unnecessary intermediate result is built up in memory) and it is therefore the prefered way to determine the count. +Internally, [COLLECTION_COUNT()](../Functions/Miscellaneous.md#collectioncount) is called. + In earlier versions with `COLLECT ... WITH COUNT INTO` available (since 2.4), -you may use the following code for better performance instead: +you may use the following code instead of *LENGTH()* for better performance: ``` FOR doc IN collection -COLLECT WITH COUNT INTO length -RETURN length + COLLECT WITH COUNT INTO length + RETURN length ``` diff --git a/Documentation/Books/AQL/Examples/Grouping.mdpp b/Documentation/Books/AQL/Examples/Grouping.mdpp index 8862d6d5ce..7cb9e93039 100644 --- a/Documentation/Books/AQL/Examples/Grouping.mdpp +++ b/Documentation/Books/AQL/Examples/Grouping.mdpp @@ -9,29 +9,29 @@ added in the query if required. *COLLECT* can be used to make a result set unique. The following query will return each distinct `age` attribute value only once: -``` -FOR u IN users - COLLECT age = u.age - RETURN age +```js +FOR u IN users + COLLECT age = u.age + RETURN age ``` This is grouping without tracking the group values, but just the group criterion (*age*) value. Grouping can also be done on multiple levels using *COLLECT*: -``` -FOR u IN users - COLLECT status = u.status, age = u.age - RETURN { status, age } +```js +FOR u IN users + COLLECT status = u.status, age = u.age + RETURN { status, age } ``` -Alternatively *RETURN DISTINCT* can be used to make a result set unique. *RETURN DISTINCT* supports a +Alternatively *RETURN DISTINCT* can be used to make a result set unique. *RETURN DISTINCT* supports a single criterion only: -``` +```js FOR u IN users - RETURN DISTINCT u.age + RETURN DISTINCT u.age ``` Note: the order of results is undefined for *RETURN DISTINCT*. @@ -41,70 +41,72 @@ Note: the order of results is undefined for *RETURN DISTINCT*. To group users by age, and return the names of the users with the highest ages, we'll issue a query like this: -``` -FOR u IN users - FILTER u.active == true - COLLECT age = u.age INTO usersByAge - SORT age DESC LIMIT 0, 5 - RETURN { +```js +FOR u IN users + FILTER u.active == true + COLLECT age = u.age INTO usersByAge + SORT age DESC LIMIT 0, 5 + RETURN { age, - users : usersByAge[*].u.name + users: usersByAge[*].u.name } +``` -[ - { - "age" : 37, - "users" : [ - "John", - "Sophia" - ] - }, - { - "age" : 36, - "users" : [ - "Fred", - "Emma" - ] - }, - { - "age" : 34, - "users" : [ - "Madison" - ] - }, - { - "age" : 33, - "users" : [ - "Chloe", - "Michael" - ] - }, - { - "age" : 32, - "users" : [ - "Alexander" - ] - } +```json +[ + { + "age": 37, + "users": [ + "John", + "Sophia" + ] + }, + { + "age": 36, + "users": [ + "Fred", + "Emma" + ] + }, + { + "age": 34, + "users": [ + "Madison" + ] + }, + { + "age": 33, + "users": [ + "Chloe", + "Michael" + ] + }, + { + "age": 32, + "users": [ + "Alexander" + ] + } ] ``` The query will put all users together by their *age* attribute. There will be one result document per distinct *age* value (let aside the *LIMIT*). For each group, we have access to the matching document via the *usersByAge* variable introduced in -the *COLLECT* statement. +the *COLLECT* statement. !SUBSECTION Variable Expansion -The *usersByAge* variable contains the full documents found, and as we're only -interested in user names, we'll use the expansion operator [\*] to extract just the +The *usersByAge* variable contains the full documents found, and as we're only +interested in user names, we'll use the expansion operator [\*] to extract just the *name* attribute of all user documents in each group. The [\*] expansion operator is just a handy short-cut. Instead of usersByAge[\*].u.name we could also write: -``` +```js FOR temp IN usersByAge - RETURN temp.u.name + RETURN temp.u.name ``` !SUBSECTION Grouping by multiple criteria @@ -113,42 +115,44 @@ To group by multiple criteria, we'll use multiple arguments in the *COLLECT* cla For example, to group users by *ageGroup* (a derived value we need to calculate first) and then by *gender*, we'll do: +```js +FOR u IN users + FILTER u.active == true + COLLECT ageGroup = FLOOR(u.age / 5) * 5, + gender = u.gender INTO group + SORT ageGroup DESC + RETURN { + ageGroup, + gender + } ``` -FOR u IN users - FILTER u.active == true - COLLECT ageGroup = FLOOR(u.age / 5) * 5, - gender = u.gender INTO group - SORT ageGroup DESC - RETURN { - ageGroup, - gender - } -[ - { - "ageGroup" : 35, - "gender" : "f" - }, - { - "ageGroup" : 35, - "gender" : "m" - }, - { - "ageGroup" : 30, - "gender" : "f" - }, - { - "ageGroup" : 30, - "gender" : "m" - }, - { - "ageGroup" : 25, - "gender" : "f" - }, - { - "ageGroup" : 25, - "gender" : "m" - } +```json +[ + { + "ageGroup": 35, + "gender": "f" + }, + { + "ageGroup": 35, + "gender": "m" + }, + { + "ageGroup": 30, + "gender": "f" + }, + { + "ageGroup": 30, + "gender": "m" + }, + { + "ageGroup": 25, + "gender": "f" + }, + { + "ageGroup": 25, + "gender": "m" + } ] ``` @@ -158,49 +162,51 @@ If the goal is to count the number of values in each group, AQL provides the spe *COLLECT WITH COUNT INTO* syntax. This is a simple variant for grouping with an additional group length calculation: +```js +FOR u IN users + FILTER u.active == true + COLLECT ageGroup = FLOOR(u.age / 5) * 5, + gender = u.gender WITH COUNT INTO numUsers + SORT ageGroup DESC + RETURN { + ageGroup, + gender, + numUsers + } ``` -FOR u IN users - FILTER u.active == true - COLLECT ageGroup = FLOOR(u.age / 5) * 5, - gender = u.gender WITH COUNT INTO numUsers - SORT ageGroup DESC - RETURN { - ageGroup, - gender, - numUsers - } -[ - { - "ageGroup" : 35, - "gender" : "f", - "numUsers" : 2 - }, - { - "ageGroup" : 35, - "gender" : "m", - "numUsers" : 2 - }, - { - "ageGroup" : 30, - "gender" : "f", - "numUsers" : 4 - }, - { - "ageGroup" : 30, - "gender" : "m", - "numUsers" : 4 - }, - { - "ageGroup" : 25, - "gender" : "f", - "numUsers" : 2 - }, - { - "ageGroup" : 25, - "gender" : "m", - "numUsers" : 2 - } +```json +[ + { + "ageGroup": 35, + "gender": "f", + "numUsers": 2 + }, + { + "ageGroup": 35, + "gender": "m", + "numUsers": 2 + }, + { + "ageGroup": 30, + "gender": "f", + "numUsers": 4 + }, + { + "ageGroup": 30, + "gender": "m", + "numUsers": 4 + }, + { + "ageGroup": 25, + "gender": "f", + "numUsers": 2 + }, + { + "ageGroup": 25, + "gender": "m", + "numUsers": 2 + } ] ``` @@ -209,45 +215,47 @@ FOR u IN users Adding further aggregation is also simple in AQL by using an *AGGREGATE* clause in the *COLLECT*: +```js +FOR u IN users + FILTER u.active == true + COLLECT ageGroup = FLOOR(u.age / 5) * 5, + gender = u.gender + AGGREGATE numUsers = LENGTH(1), + minAge = MIN(u.age), + maxAge = MAX(u.age) + SORT ageGroup DESC + RETURN { + ageGroup, + gender, + numUsers, + minAge, + maxAge + } ``` -FOR u IN users - FILTER u.active == true - COLLECT ageGroup = FLOOR(u.age / 5) * 5, - gender = u.gender - AGGREGATE numUsers = LENGTH(1), - minAge = MIN(u.age), - maxAge = MAX(u.age) - SORT ageGroup DESC - RETURN { - ageGroup, - gender, - numUsers, - minAge, - maxAge - } -[ - { - "ageGroup" : 35, - "gender" : "f", - "numUsers" : 2, - "minAge" : 36, - "maxAge" : 39, - }, - { - "ageGroup" : 35, - "gender" : "m", - "numUsers" : 2, - "minAge" : 35, - "maxAge" : 39, - }, +```json +[ + { + "ageGroup": 35, + "gender": "f", + "numUsers": 2, + "minAge": 36, + "maxAge": 39, + }, + { + "ageGroup": 35, + "gender": "m", + "numUsers": 2, + "minAge": 35, + "maxAge": 39, + }, ... ] ``` -We have used the aggregate functions *LENGTH* here (it returns the length of a array). -This is the equivalent to SQL's `SELECT g, COUNT(*) FROM ... GROUP BY g`. In addition to -*LENGTH* AQL also provides *MAX*, *MIN*, *SUM* and *AVERAGE*, *VARIANCE_POPULATION*, +We have used the aggregate functions *LENGTH* here (it returns the length of a array). +This is the equivalent to SQL's `SELECT g, COUNT(*) FROM ... GROUP BY g`. In addition to +*LENGTH* AQL also provides *MAX*, *MIN*, *SUM* and *AVERAGE*, *VARIANCE_POPULATION*, *VARIANCE_SAMPLE*, *STDDEV_POPULATION* and *STDDEV_SAMPLE* as basic aggregation functions. In AQL all aggregation functions can be run on arrays only. If an aggregation function @@ -265,38 +273,40 @@ Aggregation can also be performed after a *COLLECT* operation using other AQL co though performance-wise this is often inferior to using *COLLECT* with *AGGREGATE*. The same query as before can be turned into a post-aggregation query as shown below. Note -that this query will build and pass on all group values for all groups inside the variable +that this query will build and pass on all group values for all groups inside the variable *g*, and perform the aggregation at the latest possible stage: +```js +FOR u IN users + FILTER u.active == true + COLLECT ageGroup = FLOOR(u.age / 5) * 5, + gender = u.gender INTO g + SORT ageGroup DESC + RETURN { + ageGroup, + gender, + numUsers: LENGTH(g[*]), + minAge: MIN(g[*].u.age), + maxAge: MAX(g[*].u.age) + } ``` -FOR u IN users - FILTER u.active == true - COLLECT ageGroup = FLOOR(u.age / 5) * 5, - gender = u.gender INTO g - SORT ageGroup DESC - RETURN { - ageGroup, - gender, - numUsers : LENGTH(g[*]), - minAge : MIN(g[*].u.age), - maxAge : MAX(g[*].u.age) - } -[ - { - "ageGroup" : 35, - "gender" : "f", - "numUsers" : 2, - "minAge" : 36, - "maxAge" : 39, - }, - { - "ageGroup" : 35, - "gender" : "m", - "numUsers" : 2, - "minAge" : 35, - "maxAge" : 39, - }, +```json +[ + { + "ageGroup": 35, + "gender": "f", + "numUsers": 2, + "minAge": 36, + "maxAge": 39, + }, + { + "ageGroup": 35, + "gender": "m", + "numUsers": 2, + "minAge": 35, + "maxAge": 39, + }, ... ] ``` @@ -308,60 +318,62 @@ the aggregation during the collect operation, at the earliest possible stage. !SUBSECTION Post-filtering aggregated data To filter the results of a grouping or aggregation operation (i.e. something -similar to *HAVING* in SQL), simply add another *FILTER* clause after the *COLLECT* -statement. +similar to *HAVING* in SQL), simply add another *FILTER* clause after the *COLLECT* +statement. For example, to get the 3 *ageGroup*s with the most users in them: +```js +FOR u IN users + FILTER u.active == true + COLLECT ageGroup = FLOOR(u.age / 5) * 5 INTO group + LET numUsers = LENGTH(group) + FILTER numUsers > 2 /* group must contain at least 3 users in order to qualify */ + SORT numUsers DESC + LIMIT 0, 3 + RETURN { + "ageGroup": ageGroup, + "numUsers": numUsers, + "users": group[*].u.name + } ``` -FOR u IN users - FILTER u.active == true - COLLECT ageGroup = FLOOR(u.age / 5) * 5 INTO group - LET numUsers = LENGTH(group) - FILTER numUsers > 2 /* group must contain at least 3 users in order to qualify */ - SORT numUsers DESC - LIMIT 0, 3 - RETURN { - "ageGroup" : ageGroup, - "numUsers" : numUsers, - "users" : group[*].u.name - } -[ - { - "ageGroup" : 30, - "numUsers" : 8, - "users" : [ - "Abigail", - "Madison", - "Anthony", - "Alexander", - "Isabella", - "Chloe", - "Daniel", - "Michael" - ] - }, - { - "ageGroup" : 25, - "numUsers" : 4, - "users" : [ - "Mary", - "Mariah", - "Jim", - "Diego" - ] - }, - { - "ageGroup" : 35, - "numUsers" : 4, - "users" : [ - "Fred", - "John", - "Emma", - "Sophia" - ] - } +```json +[ + { + "ageGroup": 30, + "numUsers": 8, + "users": [ + "Abigail", + "Madison", + "Anthony", + "Alexander", + "Isabella", + "Chloe", + "Daniel", + "Michael" + ] + }, + { + "ageGroup": 25, + "numUsers": 4, + "users": [ + "Mary", + "Mariah", + "Jim", + "Diego" + ] + }, + { + "ageGroup": 35, + "numUsers": 4, + "users": [ + "Fred", + "John", + "Emma", + "Sophia" + ] + } ] ``` diff --git a/Documentation/Books/AQL/Examples/Join.mdpp b/Documentation/Books/AQL/Examples/Join.mdpp index ebefd9c78b..51a17485f0 100644 --- a/Documentation/Books/AQL/Examples/Join.mdpp +++ b/Documentation/Books/AQL/Examples/Join.mdpp @@ -24,7 +24,9 @@ FOR u IN users "user" : u.name, "friendId" : f.thisUser } +``` +```json [ { "user" : "Abigail", @@ -88,7 +90,9 @@ FOR u IN users RETURN f.thisUser ) } +``` +```json [ { "user" : "Abigail", @@ -144,7 +148,9 @@ FOR u IN users RETURN u2.name ) } +``` +```json [ { "user" : "Abigail", @@ -196,7 +202,9 @@ FOR user IN users ) FILTER LENGTH(friendList) == 0 RETURN { "user" : user.name } +``` +```json [ { "user" : "Abigail" @@ -217,12 +225,21 @@ Since we're free of schemata, there is by default no way to tell the format of t documents. So, if your documents don't contain an attribute, it defaults to null. We can however check our data for accuracy like this: -``` +```js RETURN LENGTH(FOR u IN users FILTER u.userId == null RETURN 1) +``` + +```json [ 10000 ] +``` + +```js RETURN LENGTH(FOR f IN relations FILTER f.friendOf == null RETURN 1) +``` + +```json [ 10000 ] diff --git a/Documentation/Books/AQL/Examples/ProjectionsAndFilters.mdpp b/Documentation/Books/AQL/Examples/ProjectionsAndFilters.mdpp index 110a69abd0..86a9e84122 100644 --- a/Documentation/Books/AQL/Examples/ProjectionsAndFilters.mdpp +++ b/Documentation/Books/AQL/Examples/ProjectionsAndFilters.mdpp @@ -8,7 +8,9 @@ To return three complete documents from collection *users*, the following query FOR u IN users LIMIT 0, 3 RETURN u +``` +```json [ { "_id" : "users/229886047207520", @@ -61,7 +63,9 @@ FOR u IN users "name" : u.name } } +``` +```json [ { "user" : { @@ -99,7 +103,9 @@ FOR u IN users "age" : u.age, "name" : u.name } +``` +```json [ { "age" : 37, diff --git a/Documentation/Books/AQL/Examples/README.mdpp b/Documentation/Books/AQL/Examples/README.mdpp index 8c3b6f5510..545c866a23 100644 --- a/Documentation/Books/AQL/Examples/README.mdpp +++ b/Documentation/Books/AQL/Examples/README.mdpp @@ -14,9 +14,10 @@ Some of the following example queries are executed on a collection 'users' with Note that all documents created in any collections will automatically get the following server-generated attributes: -* *_id*: A unique id, consisting of [collection name](../Glossary/README.md#collection-name) and a server-side sequence value -* *_key*: The server sequence value -* *_rev*: The document's revision id +- *_id*: A unique id, consisting of [collection name](../../Users/Appendix/Glossary.html#collection-name) + and a server-side sequence value +- *_key*: The server sequence value +- *_rev*: The document's revision id Whenever you run queries on the documents in collections, don't be surprised if these additional attributes are returned as well. @@ -25,7 +26,7 @@ Please also note that with real-world data, you might want to create additional indexes on the data (left out here for brevity). Adding indexes on attributes that are used in *FILTER* statements may considerably speed up queries. Furthermore, instead of using attributes such as *id*, *from* and *to*, you might want to use the built-in -*_id*, *_from* and *_to* attributes. Finally, [edge collection](../Glossary/README.md#edge-collection)s provide a nice way of +*_id*, *_from* and *_to* attributes. Finally, [edge collection](../../Users/Appendix/Glossary.html#edge-collection)s provide a nice way of establishing references / links between documents. These features have been left out here for brevity as well. diff --git a/Documentation/Books/AQL/ExecutionAndPerformance/ExplainingQueries.mdpp b/Documentation/Books/AQL/ExecutionAndPerformance/ExplainingQueries.mdpp index 7a4073ae16..1d401741ff 100644 --- a/Documentation/Books/AQL/ExecutionAndPerformance/ExplainingQueries.mdpp +++ b/Documentation/Books/AQL/ExecutionAndPerformance/ExplainingQueries.mdpp @@ -8,7 +8,7 @@ An explain will throw an error if the given query is syntactically invalid. Othe return the execution plan and some information about what optimizations could be applied to the query. The query will not be executed. -Explaining a query can be achieved by calling the [HTTP REST API](../HttpAqlQuery/README.md). +Explaining a query can be achieved by calling the [HTTP REST API](../../HTTP/AqlQuery/index.html). A query can also be explained from the ArangoShell using `ArangoStatement`'s `explain` method. By default, the query optimizer will return what it considers to be the *optimal plan*. The @@ -19,12 +19,12 @@ is an array of warnings that occurred during optimization or execution plan crea Each plan in the result is an object with the following attributes: - *nodes*: the array of execution nodes of the plan. The list of available node types - can be found [here](../Aql/Optimizer.md) + can be found [here](Optimizer.md) - *estimatedCost*: the total estimated cost for the plan. If there are multiple plans, the optimizer will choose the plan with the lowest total cost. - *collections*: an array of collections used in the query - *rules*: an array of rules the optimizer applied. The list of rules can be - found [here](../Aql/Optimizer.md) + found [here](Optimizer.md) - *variables*: array of variables used in the query (note: this may contain internal variables created by the optimizer) diff --git a/Documentation/Books/AQL/ExecutionAndPerformance/ParsingQueries.mdpp b/Documentation/Books/AQL/ExecutionAndPerformance/ParsingQueries.mdpp index 0425ccbbbc..0d642cf1c8 100644 --- a/Documentation/Books/AQL/ExecutionAndPerformance/ParsingQueries.mdpp +++ b/Documentation/Books/AQL/ExecutionAndPerformance/ParsingQueries.mdpp @@ -1,7 +1,7 @@ !CHAPTER Parsing queries Clients can use ArangoDB to check if a given AQL query is syntactically valid. ArangoDB provides -an [HTTP REST API](../HttpAqlQuery/README.md) for this. +an [HTTP REST API](../../HTTP/AqlQuery/index.html) for this. A query can also be parsed from the ArangoShell using `ArangoStatement`'s `parse` method. The `parse` method will throw an exception if the query is syntactically invalid. Otherwise, it will diff --git a/Documentation/Books/AQL/Extending/Conventions.mdpp b/Documentation/Books/AQL/Extending/Conventions.mdpp index eb63cc7e88..b40dd9818f 100644 --- a/Documentation/Books/AQL/Extending/Conventions.mdpp +++ b/Documentation/Books/AQL/Extending/Conventions.mdpp @@ -123,6 +123,6 @@ Documents in the *_aqlfunctions* collection (or any other system collection) should not be accessed directly, but only via the dedicated interfaces. Keep in mind that system collections are excluded from dumps created with -[arangodump](../HttpBulkImports/Arangodump.md) by default. To include AQL user +[arangodump](../../Users/Administration/Arangodump.html) by default. To include AQL user functions in a dump, the dump needs to be started with the option *--include-system-collections true*. diff --git a/Documentation/Books/AQL/Extending/Functions.mdpp b/Documentation/Books/AQL/Extending/Functions.mdpp index 2a36d8c68d..c19d266309 100644 --- a/Documentation/Books/AQL/Extending/Functions.mdpp +++ b/Documentation/Books/AQL/Extending/Functions.mdpp @@ -10,7 +10,7 @@ var aqlfunctions = require("@arangodb/aql/functions"); To register a function, the fully qualified function name plus the function code must be specified. -The [HTTP Interface](../HttpAqlUserFunctions/README.md) also offers User Functions management. +The [HTTP Interface](../../HTTP/AqlUserFunctions/index.html) also offers User Functions management. !SUBSECTION Registering an AQL user function @@ -24,7 +24,7 @@ the string evaluates to a JavaScript function definition. If a function identified by *name* already exists, the previous function definition will be updated. Please also make sure that the function code -does not violate the [Conventions](../AqlExtending/Conventions.md) for AQL +does not violate the [Conventions](Conventions.md) for AQL functions. The *isDeterministic* attribute can be used to specify whether the diff --git a/Documentation/Books/AQL/Extending/README.mdpp b/Documentation/Books/AQL/Extending/README.mdpp index e09509fc01..9166d2dfec 100644 --- a/Documentation/Books/AQL/Extending/README.mdpp +++ b/Documentation/Books/AQL/Extending/README.mdpp @@ -6,10 +6,10 @@ fully-featured programming language. To add missing functionality or to simplify queries, users may add their own functions to AQL in the selected database. These functions can be written in JavaScript, and must be -registered via the API; see [Registering Functions](../AqlExtending/Functions.md). +registered via the API; see [Registering Functions](Functions.md). In order to avoid conflicts with existing or future built-in function names, all user functions must be put into separate namespaces. Invoking a user functions is then possible by referring to the fully-qualified function name, which includes the namespace, -too; see [Conventions](../AqlExtending/Conventions.md). +too; see [Conventions](Conventions.md). diff --git a/Documentation/Books/AQL/Functions/Date.mdpp b/Documentation/Books/AQL/Functions/Date.mdpp index e1a04f9f9b..0f09c588b3 100644 --- a/Documentation/Books/AQL/Functions/Date.mdpp +++ b/Documentation/Books/AQL/Functions/Date.mdpp @@ -39,7 +39,7 @@ You are free to store age determinations of specimens, incomplete or fuzzy dates the like in different, more appropriate ways of course. AQL's date functions will most certainly not be of any help for such dates, but you can still use language constructs like [SORT](../Operations/Sort.md) (which also supports sorting of arrays) -and [indexes](../Indexing/README.md) like skiplists. +and [indexes](../../Users/Indexing/index.html) like skiplists. !SECTION Current date and time @@ -623,7 +623,7 @@ There are two recommended ways to store timestamps in ArangoDB: The sort order of both is identical due to the sort properties of ISO date strings. You can't mix both types, numbers and strings, in a single attribute however. -You can use [skiplist indices](../IndexHandling/Skiplist.md) with both date types. +You can use [skiplist indices](../../Users/Indexing/Skiplist.html) with both date types. When chosing string representations, you can work with string comparisons (less than, greater than etc.) to express time ranges in your queries while still utilizing skiplist indices: diff --git a/Documentation/Books/AQL/Functions/Document.mdpp b/Documentation/Books/AQL/Functions/Document.mdpp index aba4c7a26a..5f443e1c3b 100644 --- a/Documentation/Books/AQL/Functions/Document.mdpp +++ b/Documentation/Books/AQL/Functions/Document.mdpp @@ -79,7 +79,7 @@ HAS( { }, "name" ) // false `IS_SAME_COLLECTION(collectionName, documentHandle) → bool` collection id as the collection specified in *collection*. *document* can either be - a [document handle](../Glossary/README.md#document-handle) string, or a document with + a [document handle](../../Users/Appendix/Glossary.html#document-handle) string, or a document with an *_id* attribute. The function does not validate whether the collection actually contains the specified document, but only compares the name of the specified collection with the collection name part of the specified document. @@ -283,11 +283,11 @@ MERGE_RECURSIVE( `PARSE_IDENTIFIER(documentHandle) → parts` -Parse a [document handle](../Glossary/README.md#document-handle) and return its +Parse a [document handle](../../Users/Appendix/Glossary.html#document-handle) and return its individual parts a separate attributes. This function can be used to easily determine the -[collection name](../Glossary/README.md#collection-name) and key of a given document. +[collection name](../../Users/Appendix/Glossary.html#collection-name) and key of a given document. - **documentHandle** (string|object): a document identifier string (e.g. *_users/1234*) or a regular document from a collection. Passing either a non-string or a non-document diff --git a/Documentation/Books/AQL/Functions/Fulltext.mdpp b/Documentation/Books/AQL/Functions/Fulltext.mdpp index 3047feb1f0..a880df6c72 100644 --- a/Documentation/Books/AQL/Functions/Fulltext.mdpp +++ b/Documentation/Books/AQL/Functions/Fulltext.mdpp @@ -1,7 +1,7 @@ !CHAPTER Fulltext functions AQL offers the following functions to filter data based on -[fulltext indexes](../Indexing/Fulltext.md): +[fulltext indexes](../../Users/Indexing/Fulltext.html): !SUBSECTION FULLTEXT() diff --git a/Documentation/Books/AQL/Functions/Geo.mdpp b/Documentation/Books/AQL/Functions/Geo.mdpp index 1604781f8d..e64cee5b4f 100644 --- a/Documentation/Books/AQL/Functions/Geo.mdpp +++ b/Documentation/Books/AQL/Functions/Geo.mdpp @@ -3,7 +3,7 @@ !SECTION Geo index functions AQL offers the following functions to filter data based on -[geo indexes](../Indexing/Geo.md). These functions require the collection to have at +[geo indexes](../../Users/Indexing/Geo.html). These functions require the collection to have at least one geo index. If no geo index can be found, calling this function will fail with an error. diff --git a/Documentation/Books/AQL/Functions/Miscellaneous.mdpp b/Documentation/Books/AQL/Functions/Miscellaneous.mdpp index ccf51b2aaf..bd1ac206a2 100644 --- a/Documentation/Books/AQL/Functions/Miscellaneous.mdpp +++ b/Documentation/Books/AQL/Functions/Miscellaneous.mdpp @@ -33,7 +33,7 @@ alternatives is a document. !SUBSECTION Ternary operator For conditional evaluation, check out the -[ternary operator](../Aql/Operators.md#ternary-operator). +[ternary operator](../Operators.md#ternary-operator). !SECTION Database functions diff --git a/Documentation/Books/AQL/Functions/README.mdpp b/Documentation/Books/AQL/Functions/README.mdpp index 868d75d26c..8015115b0f 100644 --- a/Documentation/Books/AQL/Functions/README.mdpp +++ b/Documentation/Books/AQL/Functions/README.mdpp @@ -31,7 +31,7 @@ Since ArangoDB 1.3, it is possible to extend AQL with user-defined functions. These functions need to be written in JavaScript, and be registered before usage in a query. -Please refer to [Extending AQL](../AqlExtending/README.md) for more details on this. +Please refer to [Extending AQL](../Extending/index.html) for more details on this. By default, any function used in an AQL query will be sought in the built-in function namespace *_aql*. This is the default namespace that contains all AQL diff --git a/Documentation/Books/AQL/Fundamentals/BindParameters.mdpp b/Documentation/Books/AQL/Fundamentals/BindParameters.mdpp index 5ca2f7058d..ba34870035 100644 --- a/Documentation/Books/AQL/Fundamentals/BindParameters.mdpp +++ b/Documentation/Books/AQL/Fundamentals/BindParameters.mdpp @@ -24,7 +24,7 @@ letter, digit or the underscore symbol. Bind variables represent a value like a string, and must not be put in quotes. If you need to do string processing (concatenation, etc.) in the AQL query, you need -[to use string functions to do so](../Aql/StringFunctions.md): +[to use string functions to do so](../Functions/String.md): FOR u IN users FILTER u.id == CONCAT('prefix', @id, 'suffix') && u.name == @name @@ -40,5 +40,8 @@ when using the bind parameter in a query, two *@* symbols must be used). RETURN u -Specific information about parameters binding can also be found in [Aql With Web Interface](AqlWithWebInterface.md) and [Aql With Arangosh](AqlWithArangosh.md), and [HTTP Interface for AQL Queries](../HttpAqlQuery/README.md) +Specific information about parameters binding can also be found in +[Aql With Web Interface](../Invocation/WithWebInterface.md) and +[Aql With Arangosh](../Invocation/WithArangosh.md), and +[HTTP Interface for AQL Queries](../../HTTP/AqlQuery/index.html) diff --git a/Documentation/Books/AQL/Fundamentals/QueryErrors.mdpp b/Documentation/Books/AQL/Fundamentals/QueryErrors.mdpp index 4b9bd05fc0..f424cad940 100644 --- a/Documentation/Books/AQL/Fundamentals/QueryErrors.mdpp +++ b/Documentation/Books/AQL/Fundamentals/QueryErrors.mdpp @@ -26,6 +26,6 @@ examples that will cause run-time errors are: includes unary (logical not/negation), binary (logical and, logical or), and the ternary operators -Please refer to the [Arango Errors](../ErrorCodes/README.md) page for a list of error codes and -meanings. +Please refer to the [Arango Errors](../../Users/Appendix/ErrorCodes.html) page +for a list of error codes and meanings. diff --git a/Documentation/Books/AQL/Fundamentals/QueryResults.mdpp b/Documentation/Books/AQL/Fundamentals/QueryResults.mdpp index a24b09d3c1..959ba48bf6 100644 --- a/Documentation/Books/AQL/Fundamentals/QueryResults.mdpp +++ b/Documentation/Books/AQL/Fundamentals/QueryResults.mdpp @@ -11,34 +11,47 @@ For example, when returning data from a collection with inhomogeneous documents without modification, the result values will as well have an inhomogeneous structure. Each result value itself is a document: - 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" } ] +```js +FOR u IN users + RETURN u +``` + +```json +[ { "id": 1, "name": "John", "active": false }, + { "age": 32, "id": 2, "name": "Vanessa" }, + { "friends": [ "John", "Vanessa" ], "id": 3, "name": "Amy" } ] +``` However, if a fixed set of attributes from the collection is queried, then the query result values will have a homogeneous structure. Each result value is still a document: - FOR u IN users - RETURN { "id" : u.id, "name" : u.name } - - [ { "id" : 1, "name" : "John" }, - { "id" : 2, "name" : "Vanessa" }, - { "id" : 3, "name" : "Amy" } ] +```js +FOR u IN users + RETURN { "id": u.id, "name": u.name } +``` + +```json +[ { "id": 1, "name": "John" }, + { "id": 2, "name": "Vanessa" }, + { "id": 3, "name": "Amy" } ] +``` It is also possible to query just scalar values. In this case, the result set is an array of scalars, and each result value is a scalar value: - FOR u IN users - RETURN u.id - - [ 1, 2, 3 ] +```js +FOR u IN users + RETURN u.id +``` + +```json +[ 1, 2, 3 ] +``` If a query does not produce any results because no matching data can be found, it will produce an empty result array: - [ ] - +```json +[ ] +``` diff --git a/Documentation/Books/AQL/Fundamentals/Syntax.mdpp b/Documentation/Books/AQL/Fundamentals/Syntax.mdpp index f545948d08..ea1e35c905 100644 --- a/Documentation/Books/AQL/Fundamentals/Syntax.mdpp +++ b/Documentation/Books/AQL/Fundamentals/Syntax.mdpp @@ -156,8 +156,8 @@ The example can alternatively written as: 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. -Please refer to the [Naming Conventions in ArangoDB](../NamingConventions/CollectionNames.md) about collection naming -conventions. +Please refer to the [Naming Conventions in ArangoDB](../../Users/DataModeling/NamingConventions/CollectionNames.html) +about collection naming conventions. !SUBSUBSECTION Attribute names @@ -166,8 +166,8 @@ attribute name must be used. This is because multiple collections with ambiguous attribute names may be used in a query. To avoid any ambiguity, it is not allowed to refer to an unqualified attribute name. -Please refer to the [Naming Conventions in ArangoDB](../NamingConventions/AttributeNames.md) for more information about the -attribute naming conventions. +Please refer to the [Naming Conventions in ArangoDB](../../Users/DataModeling/NamingConventions/AttributeNames.html) +for more information about the attribute naming conventions. FOR u IN users FOR f IN friends diff --git a/Documentation/Books/AQL/Fundamentals/TypeValueOrder.mdpp b/Documentation/Books/AQL/Fundamentals/TypeValueOrder.mdpp index 7ccb65c340..2d39ef692e 100644 --- a/Documentation/Books/AQL/Fundamentals/TypeValueOrder.mdpp +++ b/Documentation/Books/AQL/Fundamentals/TypeValueOrder.mdpp @@ -9,7 +9,7 @@ data values if the operands have the same data types. The following type order is used when comparing data types: - null < bool < number < string < array < object / document + null < bool < number < string < array/list < object/document This means *null* is the smallest type in AQL and *document* is the type with the highest order. If the compared operands have a different type, then the diff --git a/Documentation/Books/AQL/Graphs/Functions.mdpp b/Documentation/Books/AQL/Graphs/Functions.mdpp index fb5f50fcdf..f4fcc6071e 100644 --- a/Documentation/Books/AQL/Graphs/Functions.mdpp +++ b/Documentation/Books/AQL/Graphs/Functions.mdpp @@ -2,7 +2,7 @@ AQL has the following functions to traverse loosely-structured graphs consisting of an edge collection and plus the vertices connected by it. If you have created a graph -using the general-graph module you may want to use its more specific [Graph operations](../Aql/GraphOperations.md) +using the general-graph module you may want to use its more specific [Graph operations](Operations.md) instead. @@ -74,8 +74,8 @@ with the option *includeVertices* set to true. !SECTION General Purpose Traversals -General purpose traversals with its extendability by visitor functions offer more possibilities over the newer [AQL graph traversals](../Aql/GraphTraversals.md), -however unless you need some of these features you should [prefer AQL graph traversals](../Aql/GraphTraversals.md). +General purpose traversals with its extendability by visitor functions offer more possibilities over the newer [AQL graph traversals](Traversals.md), +however unless you need some of these features you should [prefer AQL graph traversals](Traversals.md). !SUBSECTION Traversal *TRAVERSAL(vertexcollection, edgecollection, startVertex, direction, options)*: @@ -516,7 +516,7 @@ path is a document consisting of the following attributes: RETURN p.vertices[*].name !SECTION Graph consistency -When [using the graph management functions to remove vertices](../GeneralGraphs/Management.md#remove-a-vertex) +When [using the graph management functions to remove vertices](Management.md#remove-a-vertex) you have the guaranty that all referencing edges are also removed. However, if you use document features alone to remove vertices, no edge collections will be adjusted. This results in an edge with its `_from` or `_to` attribute referring to vanished vertices. @@ -532,7 +532,7 @@ In order to keep the result set consistent between *includeData* enabled or disa When using any of AQL's general purpose traversal functions, please make sure that the graph does not contain cycles, or that you at least specify some maximum depth or uniqueness -criteria for a traversal. In contrast [AQL graph traversals](../Aql/GraphTraversals.md) won't trap on cycles. +criteria for a traversal. In contrast [AQL graph traversals](Traversals.md) won't trap on cycles. If no bounds are set, a traversal may run into an endless loop in a cyclic graph or sub-graph. Even in a non-cyclic graph, traversing far into the graph may consume a lot of processing diff --git a/Documentation/Books/AQL/Graphs/Operations.mdpp b/Documentation/Books/AQL/Graphs/Operations.mdpp index ebddef80bb..6947dfe895 100644 --- a/Documentation/Books/AQL/Graphs/Operations.mdpp +++ b/Documentation/Books/AQL/Graphs/Operations.mdpp @@ -24,9 +24,9 @@ the amount of vertices in the graph, *x* the amount of start vertices and *y* th target vertices. Hence a suggestion may be to use Dijkstra when x\*y < n and the functions supports choosing your algorithm. !SUBSECTION Example Graph -All examples in this chapter will use [this simple city graph](../Graphs/README.md#the-city-graph): +All examples in this chapter will use [this simple city graph](../../Users/Graphs/index.html#the-city-graph): -![Cities Example Graph](../Graphs/cities_graph.png) +![Cities Example Graph](../../Users/Graphs/cities_graph.png) !SUBSECTION Edges and Vertices related functions @@ -576,7 +576,7 @@ The complexity of this function strongly depends on the usage. - *connectName*: The result attribute which contains the connection. - *options* (optional): An object containing options, see - [Graph Traversals](../Aql/GraphOperations.md#graphtraversal): + [Graph Traversals](#graphtraversal): **Examples** @@ -1092,9 +1092,8 @@ outbound paths. `GRAPH_RADIUS (graphName, options)` -*The GRAPH\_RADIUS function returns the -[radius](http://en.wikipedia.org/wiki/Eccentricity_%28graph_theory%29) -of a graph.* +The GRAPH_RADIUS function returns the +[radius](http://en.wikipedia.org/wiki/Eccentricity_%28graph_theory%29) of a graph. The complexity of the function is described [here](#the-complexity-of-the-shortest-path-algorithms). diff --git a/Documentation/Books/AQL/Graphs/README.mdpp b/Documentation/Books/AQL/Graphs/README.mdpp index 174cfa8668..8e4b710bcd 100644 --- a/Documentation/Books/AQL/Graphs/README.mdpp +++ b/Documentation/Books/AQL/Graphs/README.mdpp @@ -1,15 +1,15 @@ !CHAPTER Graphs in AQL -As you already [read about graphs in ArangoDB](../Graphs/README.md) you can have several views on graphs. +As you already [read about graphs in ArangoDB](../../Users/Graphs/index.html) you can have several views on graphs. There are also several ways to work with graphs in AQL. You can use named graphs where ArangoDB manages the collections involved in one graph. You can also use graph functions on a combination of document and edge collections. -named graphs are defined though the [graph-module](../GeneralGraphs/README.md), that contains the name of the graph, and the vertex and edge collections involved. +named graphs are defined though the [graph-module](../../Users/Graphs/GeneralGraphs/index.html), that contains the name of the graph, and the vertex and edge collections involved. Since the management functions are layered on top of simple sets of document and edge collections, you can also use regular AQL functions to work with them. In AQL you can reach several graphing functions: -* [AQL Traversals](GraphTraversals.md) is making full use of optimisations and therefore best performance is to be expected. It can work on named graphs and loosely coupled collection sets (aka anonymous graphs). You can use AQL filter conditions on traversals. -* [Named graph Operations](GraphOperations.md) work on named graphs; offer a versatile range of parameters. -* [Other graph functions](GraphFunctions.md) work on single edge collection (which may also be part of named graphs). +* [AQL Traversals](Traversals.md) is making full use of optimisations and therefore best performance is to be expected. It can work on named graphs and loosely coupled collection sets (aka anonymous graphs). You can use AQL filter conditions on traversals. +* [Named graph Operations](Operations.md) work on named graphs; offer a versatile range of parameters. +* [Other graph functions](Functions.md) work on single edge collection (which may also be part of named graphs). diff --git a/Documentation/Books/AQL/Graphs/Traversals.mdpp b/Documentation/Books/AQL/Graphs/Traversals.mdpp index a21d51a59b..37f3a037a0 100644 --- a/Documentation/Books/AQL/Graphs/Traversals.mdpp +++ b/Documentation/Books/AQL/Graphs/Traversals.mdpp @@ -18,7 +18,7 @@ For all vertices that where visited during this process in the range between *mi Let's take a look at a simple example to explain how it works. This is the graph that we are going to traverse: -![traversal graph](../Graphs/traversal_graph.png) +![traversal graph](../../Users/Graphs/traversal_graph.png) Now we use the following parameters for our query: @@ -27,36 +27,36 @@ Now we use the following parameters for our query: 3. We use a *max-depth* of 2. 4. We follow only *outbound* direction of edges -![traversal graph step 1](../Graphs/traversal_graph1.png) +![traversal graph step 1](../../Users/Graphs/traversal_graph1.png) Now it walks to one of the direct neighbors of **A**, say **B** (NOTE: ordering is not guaranteed): -![traversal graph step 2](../Graphs/traversal_graph2.png) +![traversal graph step 2](../../Users/Graphs/traversal_graph2.png) The query will remember the state (red circle) and will emit the first result **A** -> **B** (black box). This will also prevent the traverser to be trapped in cycles. Now again it will visit one of the direct neighbors of **B**, say **E**: -![traversal graph step 3](../Graphs/traversal_graph3.png) +![traversal graph step 3](../../Users/Graphs/traversal_graph3.png) We have limited the query with a *max-depth* of *2* then it will not pick any neighbor of **E** as the path from **A** to **E** already requires *2* steps. Instead we will go back one level to **B** and continue with any other direct neighbor there: -![traversal graph step 4](../Graphs/traversal_graph4.png) +![traversal graph step 4](../../Users/Graphs/traversal_graph4.png) Again after we produced this result we will step back to **B**. But there is no neighbor of **B** left that we have not yet visited. Hence we go another step back to **A** and continue with any other neighbor there. -![traversal graph step 5](../Graphs/traversal_graph5.png) +![traversal graph step 5](../../Users/Graphs/traversal_graph5.png) And identical to the iterations before we will visit **H**: -![traversal graph step 6](../Graphs/traversal_graph6.png) +![traversal graph step 6](../../Users/Graphs/traversal_graph6.png) And **J**: -![traversal graph step 7](../Graphs/traversal_graph7.png) +![traversal graph step 7](../../Users/Graphs/traversal_graph7.png) And after these steps there is no further result left. So all together this query has returned the following paths: @@ -72,7 +72,7 @@ So all together this query has returned the following paths: !SUBSECTION Syntax Now let's see how we can write a query that follows this schema. -You have two options here, you can either use a named graph (see [the graphs chapter](../Graphs/README.md) on how to create it) or anonymous graphs. +You have two options here, you can either use a named graph (see [the graphs chapter](index.html) on how to create it) or anonymous graphs. !SUBSUBSECTION Working on named graphs: @@ -81,18 +81,18 @@ You have two options here, you can either use a named graph (see [the graphs cha `OUTBOUND|INBOUND|ANY` startVertex `GRAPH` graphName - - `FOR` - emits up to three variables: - - **vertex**: the current vertex in a traversal - - **edge**: *(optional)* the current edge in a traversal - - **path**: *(optional, requires edge to be present)* an object representing the current path with two members: - - `vertices`: an array of all vertices on this path. - - `edges`: an array of all edges on this path. - - `IN` `MIN`..`MAX` `OUTBOUND` startVertex `GRAPH` graphName - - `OUTBOUND|INBOUND|ANY` traversal will be done for outbound / inbound / inbound+outbound pointing edges - - **startVertex**: one vertex where the traversal will originate from, this can be specified in the form of an id string or in the form of a document with the attribute `_id`. All other values will lead to a warning and an empty result. If the specified id does not exist, the result is empty as well and there is no warning. - - **graphName**: the name identifying the named graph. It's vertex and edge collections will be looked up. - - `MIN`: edges and vertices returned by this query will start at the traversal depth of `MIN` (thus edges and vertices below will not be returned). If not specified, defaults to `1`, which is the minimal possible value. - - `MAX`: up to `MAX` length paths are traversed. If omitted in the query, `MAX` equals `MIN`. Thus only the vertices and edges in the range of `MIN` are returned. +- `FOR` - emits up to three variables: + - **vertex**: the current vertex in a traversal + - **edge**: *(optional)* the current edge in a traversal + - **path**: *(optional, requires edge to be present)* an object representing the current path with two members: + - `vertices`: an array of all vertices on this path. + - `edges`: an array of all edges on this path. +- `IN` `MIN`..`MAX` `OUTBOUND` startVertex `GRAPH` graphName + - `OUTBOUND|INBOUND|ANY` traversal will be done for outbound / inbound / inbound+outbound pointing edges + - **startVertex**: one vertex where the traversal will originate from, this can be specified in the form of an id string or in the form of a document with the attribute `_id`. All other values will lead to a warning and an empty result. If the specified id does not exist, the result is empty as well and there is no warning. + - **graphName**: the name identifying the named graph. It's vertex and edge collections will be looked up. + - `MIN`: edges and vertices returned by this query will start at the traversal depth of `MIN` (thus edges and vertices below will not be returned). If not specified, defaults to `1`, which is the minimal possible value. + - `MAX`: up to `MAX` length paths are traversed. If omitted in the query, `MAX` equals `MIN`. Thus only the vertices and edges in the range of `MIN` are returned. !SUBSUBSECTION Working on collection sets: @@ -171,7 +171,7 @@ This is because for all results in depth `1` the second edge does not exist and !SUBSUBSECTION Examples We will create a simple symmetric traversal demonstration graph: -![traversal graph](../Graphs/traversal_graph.png) +![traversal graph](../../Users/Graphs/traversal_graph.png) @startDocuBlockInline GRAPHTRAV_01_create_graph @EXAMPLE_ARANGOSH_OUTPUT{GRAPHTRAV_01_create_graph} @@ -260,7 +260,8 @@ Due to this we will see duplicate nodes in the result. !SUBSUBSECTION Use the AQL explainer for optimizations -Now lets have a look what the optimizer does behind the curtains and inspect traversal queries using [the explainer](Optimizer.md): +Now lets have a look what the optimizer does behind the curtains and inspect traversal queries using +[the explainer](../ExecutionAndPerformance/Optimizer.md): @startDocuBlockInline GRAPHTRAV_07_traverse_7 @@ -284,6 +285,6 @@ And finally clean it up again: @endDocuBlock GRAPHTRAV_99_drop_graph -If this traversal is not powerful enough for your needs, so you cannot describe your conditions as AQL filter statements you might want to look at [manually crafted traverser](../Traversals/README.md). +If this traversal is not powerful enough for your needs, so you cannot describe your conditions as AQL filter statements you might want to look at [manually crafted traverser](../../Users/Graphs/Traversals/index.html). -[See here for more traversal examples](../AqlExamples/CombiningGraphTraversals.md). +[See here for more traversal examples](../Examples/CombiningGraphTraversals.md). diff --git a/Documentation/Books/AQL/Invocation/README.mdpp b/Documentation/Books/AQL/Invocation/README.mdpp index b1525d5eb8..429976c302 100644 --- a/Documentation/Books/AQL/Invocation/README.mdpp +++ b/Documentation/Books/AQL/Invocation/README.mdpp @@ -1,11 +1,11 @@ !CHAPTER How to invoke AQL 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). +API description is available at [HTTP Interface for AQL Query Cursors](../../HTTP/AqlQueryCursor/index.html). -The ArangoDB Web Interface has a [specific tab for AQL queries execution](AqlWithWebInterface.md). +The ArangoDB Web Interface has a [specific tab for AQL queries execution](../Invocation/WithWebInterface.md). -You can run [AQL queries from the ArangoDB Shell](AqlWithArangosh.md) with the *_query* and *_createStatement* methods of the *db* object. +You can run [AQL queries from the ArangoDB Shell](../Invocation/WithArangosh.md) with the *_query* and *_createStatement* methods of the *db* object. This chapter also describes how to use bind parameters, statistics, counting and cursors with arangosh. diff --git a/Documentation/Books/AQL/Invocation/WithArangosh.mdpp b/Documentation/Books/AQL/Invocation/WithArangosh.mdpp index f7ff46455b..209ae5724c 100644 --- a/Documentation/Books/AQL/Invocation/WithArangosh.mdpp +++ b/Documentation/Books/AQL/Invocation/WithArangosh.mdpp @@ -88,7 +88,7 @@ It is always possible to retrieve statistics for a query with the *getExtra* met @END_EXAMPLE_ARANGOSH_OUTPUT @endDocuBlock 03_workWithAQL_getExtra -The meaning of the statistics values is described in [Execution statistics](QueryStatistics.md). +The meaning of the statistics values is described in [Execution statistics](../ExecutionAndPerformance/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) diff --git a/Documentation/Books/AQL/Invocation/WithWebInterface.mdpp b/Documentation/Books/AQL/Invocation/WithWebInterface.mdpp index d64dc1c935..6d2e244582 100644 --- a/Documentation/Books/AQL/Invocation/WithWebInterface.mdpp +++ b/Documentation/Books/AQL/Invocation/WithWebInterface.mdpp @@ -12,18 +12,22 @@ They are defined as JSON values, the same format that is used for bind parameter Here is an example: - for doc in @@collection - FILTER CONTAINS(LOWER(doc.author), @search, false) - return {"name":doc.name, "descr": doc.description, "author":doc.author} +```js +FOR doc IN @@collection +FILTER CONTAINS(LOWER(doc.author), @search, false) +RETURN { "name": doc.name, "descr": doc.description, "author": doc.author } +``` Bind parameter: - { - "@collection":"_apps", - "search":"arango" - } +```js +{ + "@collection": "_apps", + "search": "arango" +} +``` -An overview of Bind Parameters may be found in [Aql Fundamentals](BindParameters.md). +An overview of Bind Parameters may be found in [Aql Fundamentals](../Fundamentals/BindParameters.md). Queries can also be saved in the AQL editor along with their bind parameter values for later reuse. This data is stored in the user profile in the current database (in the *_users* system table). diff --git a/Documentation/Books/AQL/Operations/Filter.mdpp b/Documentation/Books/AQL/Operations/Filter.mdpp index 27b585a6a1..cbe34ecd35 100644 --- a/Documentation/Books/AQL/Operations/Filter.mdpp +++ b/Documentation/Books/AQL/Operations/Filter.mdpp @@ -34,7 +34,7 @@ In the above example, will be included in the result all array elements from *us 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 +You may refer to the chapter [Accessing Data from Collections](../Fundamentals/DocumentData.md) for a description of the impact of non-existent or null attributes. diff --git a/Documentation/Books/AQL/Operations/For.mdpp b/Documentation/Books/AQL/Operations/For.mdpp index ce3a555eb8..98ed732458 100644 --- a/Documentation/Books/AQL/Operations/For.mdpp +++ b/Documentation/Books/AQL/Operations/For.mdpp @@ -14,7 +14,7 @@ There also is a special case for graph traversals: FOR vertex-variable-name, edge-variable-name, path-variable-name IN traversal-expression ``` -For this special case see [the graph traversals chapter](../Aql/GraphTraversals.md). +For this special case see [the graph traversals chapter](../Graphs/Traversals.md). For all other cases read on: Each array element returned by *expression* is visited exactly once. It is diff --git a/Documentation/Books/AQL/Operations/Insert.mdpp b/Documentation/Books/AQL/Operations/Insert.mdpp index 74df65f1dd..43fb62da07 100644 --- a/Documentation/Books/AQL/Operations/Insert.mdpp +++ b/Documentation/Books/AQL/Operations/Insert.mdpp @@ -5,7 +5,7 @@ single server, an insert operation is executed transactionally in an all-or-noth fashion. For sharded collections, the entire insert operation is not transactional. Each *INSERT* operation is restricted to a single collection, and the -[collection name](../Glossary/README.md#collection-name) must not be dynamic. +[collection name](../../Users/Appendix/Glossary.html#collection-name) must not be dynamic. Only a single *INSERT* statement per collection is allowed per AQL query, and it cannot be followed by read operations that access the same collection, by traversal operations, or AQL functions that can read documents. @@ -29,7 +29,7 @@ FOR i IN 1..100 INSERT { value: i } IN numbers ``` -When inserting into an [edge collection](../Glossary/README.md#edge-collection), it is mandatory to specify the attributes +When inserting into an [edge collection](../../Users/Appendix/Glossary.html#edge-collection), it is mandatory to specify the attributes *_from* and *_to* in document: ``` diff --git a/Documentation/Books/AQL/Operations/README.mdpp b/Documentation/Books/AQL/Operations/README.mdpp index a3ee5c4541..8eaeff5870 100644 --- a/Documentation/Books/AQL/Operations/README.mdpp +++ b/Documentation/Books/AQL/Operations/README.mdpp @@ -2,16 +2,16 @@ The following high-level operations are described here after: -* [FOR](../AqlOperations/For.md) : to iterate over all elements of an array. -* [RETURN](../AqlOperations/Return.md) : to produce the result of a query. -* [FILTER](../AqlOperations/Filter.md) : to restrict the results to elements that match an arbitrary logical condition. -* [SORT](../AqlOperations/Sort.md) : to force a sort of the array of already produced intermediate results. -* [LIMIT](../AqlOperations/Limit.md) : to reduce the number of elements in the result to at most the specified number. -* [LET](../AqlOperations/Let.md) : to assign an arbitrary value to a variable. -* [COLLECT](../AqlOperations/Collect.md) : to group an array by one or multiple group criteria. -* [REMOVE](../AqlOperations/Remove.md) : to remove documents from a collection. -* [UPDATE](../AqlOperations/Update.md) : to partially update documents in a collection. -* [REPLACE](../AqlOperations/Replace.md) : to completely replace documents in a collection. -* [INSERT](../AqlOperations/Insert.md) : to insert new documents into a collection. -* [UPSERT](../AqlOperations/Upsert.md) : to update an existing document, or create it in the case it does not exist. +* [FOR](For.md) : to iterate over all elements of an array. +* [RETURN](Return.md) : to produce the result of a query. +* [FILTER](Filter.md) : to restrict the results to elements that match an arbitrary logical condition. +* [SORT](Sort.md) : to force a sort of the array of already produced intermediate results. +* [LIMIT](Limit.md) : to reduce the number of elements in the result to at most the specified number. +* [LET](Let.md) : to assign an arbitrary value to a variable. +* [COLLECT](Collect.md) : to group an array by one or multiple group criteria. +* [REMOVE](Remove.md) : to remove documents from a collection. +* [UPDATE](Update.md) : to partially update documents in a collection. +* [REPLACE](Replace.md) : to completely replace documents in a collection. +* [INSERT](Insert.md) : to insert new documents into a collection. +* [UPSERT](Upsert.md) : to update an existing document, or create it in the case it does not exist. diff --git a/Documentation/Books/AQL/Operations/Remove.mdpp b/Documentation/Books/AQL/Operations/Remove.mdpp index 7da97d7a6f..97574a731e 100644 --- a/Documentation/Books/AQL/Operations/Remove.mdpp +++ b/Documentation/Books/AQL/Operations/Remove.mdpp @@ -7,7 +7,7 @@ all-or-nothing fashion. For sharded collections, the entire remove operation is not transactional. Each *REMOVE* operation is restricted to a single collection, and the -[collection name](../Glossary/README.md#collection-name) must not be dynamic. +[collection name](../../Users/Appendix/Glossary.html#collection-name) must not be dynamic. Only a single *REMOVE* statement per collection is allowed per AQL query, and it cannot be followed by read operations that access the same collection, by traversal operations, or AQL functions that can read documents. @@ -20,7 +20,8 @@ REMOVE key-expression IN collection options *collection* must contain the name of the collection to remove the documents from. *key-expression* must be an expression that contains the document identification. -This can either be a string (which must then contain the [document key](../Glossary/README.md#document-key)) or a +This can either be a string (which must then contain the +[document key](../../Users/Appendix/Glossary.html#document-key)) or a document, which must contain a *_key* attribute. The following queries are thus equivalent: diff --git a/Documentation/Books/AQL/Operations/Replace.mdpp b/Documentation/Books/AQL/Operations/Replace.mdpp index 7d9c7b3a45..8ba1cd11c8 100644 --- a/Documentation/Books/AQL/Operations/Replace.mdpp +++ b/Documentation/Books/AQL/Operations/Replace.mdpp @@ -5,7 +5,7 @@ single server, the replace operation is executed transactionally in an all-or-no fashion. For sharded collections, the entire replace operation is not transactional. Each *REPLACE* operation is restricted to a single collection, and the -[collection name](../Glossary/README.md#collection-name) must not be dynamic. +[collection name](../../Users/Appendix/Glossary.html#collection-name) must not be dynamic. Only a single *REPLACE* statement per collection is allowed per AQL query, and it cannot be followed by read operations that access the same collection, by traversal operations, or AQL functions that can read documents. diff --git a/Documentation/Books/AQL/Operations/Update.mdpp b/Documentation/Books/AQL/Operations/Update.mdpp index 3aaa5ea60d..edf03d37a1 100644 --- a/Documentation/Books/AQL/Operations/Update.mdpp +++ b/Documentation/Books/AQL/Operations/Update.mdpp @@ -5,7 +5,7 @@ single server, updates are executed transactionally in an all-or-nothing fashion For sharded collections, the entire update operation is not transactional. Each *UPDATE* operation is restricted to a single collection, and the -[collection name](../Glossary/README.md#collection-name) must not be dynamic. +[collection name](../../Users/Appendix/Glossary.html#collection-name) must not be dynamic. Only a single *UPDATE* statement per collection is allowed per AQL query, and it cannot be followed by read operations that access the same collection, by traversal operations, or AQL functions that can read documents. diff --git a/Documentation/Books/AQL/Operations/Upsert.mdpp b/Documentation/Books/AQL/Operations/Upsert.mdpp index 845091a8bb..9405b83418 100644 --- a/Documentation/Books/AQL/Operations/Upsert.mdpp +++ b/Documentation/Books/AQL/Operations/Upsert.mdpp @@ -6,7 +6,7 @@ On a single server, upserts are executed transactionally in an all-or-nothing fa For sharded collections, the entire update operation is not transactional. Each *UPSERT* operation is restricted to a single collection, and the -[collection name](../Glossary/README.md#collection-name) must not be dynamic. +[collection name](../../Users/Appendix/Glossary.html#collection-name) must not be dynamic. Only a single *UPSERT* statement per collection is allowed per AQL query, and it cannot be followed by read operations that access the same collection, by traversal operations, or AQL functions that can read documents. diff --git a/Documentation/Books/AQL/Operators.mdpp b/Documentation/Books/AQL/Operators.mdpp index ba306cf734..ba7288b022 100644 --- a/Documentation/Books/AQL/Operators.mdpp +++ b/Documentation/Books/AQL/Operators.mdpp @@ -264,7 +264,8 @@ will produce the following result: !SUBSUBSECTION Array operators -AQL provides [array operators](ArrayOperators.md) [\*] for array variable expansion and [\*\*] for array contraction. +AQL provides [array operators](Advanced/ArrayOperators.md) [\*] for +array variable expansion and [\*\*] for array contraction. !SUBSUBSECTION Operator precedence diff --git a/Documentation/Books/AQL/README.mdpp b/Documentation/Books/AQL/README.mdpp index 5a8ee493a9..302a1a79ba 100644 --- a/Documentation/Books/AQL/README.mdpp +++ b/Documentation/Books/AQL/README.mdpp @@ -26,5 +26,5 @@ The syntax of AQL queries is different to SQL, even if some keywords overlap. Nevertheless, AQL should be easy to understand for anyone with an SQL background. For some example queries, please refer to the pages [Data Modification Queries](DataModification.md) and -[Usual query patterns](../AqlExamples/README.md). +[Usual query patterns](Examples/README.md).