Accessing data from collections with AQL
You can access collection data by looping over a collection and reading document attributes, with non-existing attributes returning a null
value
A collection can be thought of as an array of documents. To access the documents,
use a FOR
operation to iterate over a
collection using its name, like FOR doc IN collection ...
.
Note that when iterating over a collection, the order of documents is undefined.
To establish an explicit and deterministic order for the documents, use a
SORT
operation in addition.
Data in collections is stored in documents, which are JSON objects. Each document potentially has different attributes than other documents. This is true even for documents of the same collection.
It is therefore quite normal to encounter documents that do not have some or all
of the attributes that are queried in an AQL query. In this case, the
non-existing attributes in the document are treated as if they would exist
with a value of null
. This means that comparing a document attribute to
null
returns true
if the document has the particular attribute and the
attribute has a value of null
, or that the document does not have the
particular attribute at all.
For example, the following query returns all documents from the collection
users
that have a value of null
in the attribute name
, plus all documents
from users
that do not have the name
attribute at all:
FOR u IN users
FILTER u.name == null
RETURN u
Furthermore, null
is less than any other value (excluding null
itself). That
means documents with non-existing attributes may be included in the result
when comparing attribute values with the less than or less equal operators.
For example, the following query returns all documents from the collection
users
that have an attribute age
with a value less than 39
, but also all
documents from the collection that do not have the attribute age
at all.
FOR u IN users
FILTER u.age < 39
RETURN u
This behavior should always be taken into account when writing queries.
To distinguish between an explicit null
value and the implicit null
value
you get if you access a non-existent attribute, you can use the
HAS() function
. The following query
only returns documents that have a name
attribute with a null
value:
FOR u IN users
FILTER u.name == null AND HAS(u, "name")
RETURN u
To exclude implicit as well as explicit null
values in a query that uses
<
or <=
comparison operators to limit the upper bound, you can add a check
for the lower bound:
FOR u IN users
FILTER u.age > null AND u.age < 39
// or potentially
//FILTER u.age >= 0 AND u.age < 39
// which can be replaced with
//FILTER RANGE(u.age, 0, 39, true, false)
RETURN u