AQL Queries

Query Builder is abstraction layer around AQL to work with it in more pythonic way.

Simplest start point is to use arango.collection.Collection.query.

Simple example:

from arango import collection as c

# create collection
c.test1.create()

c.test1.docs.create({"name": "John", "email": "john@example.com"})
c.test1.docs.create({"name": "Jane", "email": "jane@example.com"})

c.test1.query.filter("obj.name == 'John'").build_query()

c.test1.delete()

will generate AQL query:

FOR obj IN test
    FILTER obj.name == 'John'
RETURN
    obj

AQL Query Builder API

This API typically accesible via query method of collection instance.

Builder methods to generate AQL query:

class arango.aql.AQLQuery(connection=None, collection=None, no_cache=False)

An abstraction layer to generate simple AQL queries.

bind(**kwargs)

Bind some data to AQL Query. Technically it’s just a proxy to arango.cursor.Cursor.bind method which attach variables to the Cursor.

It’s mostly for avoding any kind of query injetions.

data = c.test.query.filter("obj.name == @name")\
                  .bind(name="Jane")\
                  .execute().first

assert data != None
assert data.body["name"] == "Jane"
build_query()

Build AQL query and return it as a string. This is good start to debug generated AQL queries.

collect(*pairs, **kwargs)

Specify COLLECT operators, it’s possible to use it multiple times

COLLECT variable-name = expression
COLLECT variable-name = expression INTO groups

In python

c.test.query
      .collect("emails", "u.email")
      .collect("names", "u.name", into="eml")
      .result(emails="eml",
              names="names")
cursor(**kwargs)

Method to provide custom arguments for arango.cursor.Cursor instance. All keywords arguments except bindVars may be changed.

execute(wrapper=None)

Execute query: create cursor, put binded variables and return instance of arango.cursor.Cursor object

filter(condition)

Filter query by condition condition. It’s possible to add multiple filter expressions.

FILTER condition

For exmaple code in python

c.test.query
      .filter("a==b && c==d")
      .filter("d == m")
iter(name)

FOR cycle temporary variable, variable-name in AQL expression:

FOR variable-name IN expression
let(name, value)

Add LET operation

LET variable-name = expression
limit(count, offset=None)

Limit results with count items. By default offset is 0.

query.limit(100, offset=10)
over(expression)

expression in FOR cycle

FOR variable-name IN expression
result(*args, **kwargs)

Expression which will be added as RETURN of AQL. You can specify:

  • single name, like q.result("u")
  • named arguments, like q.result(users="u", members="m") which transform into RETURN {users: u, members: m}
  • fields named argument, like q.result(fields={"key-a": "a"}) to work with names which are not supported by Python syntax.
sort(*args)

Sort result by criterias from args.

query.sort("u.email", "u.first_name DESC")
     .sort("u.last_name")

Helpers to work with query variables and functions.

arango.aql.V(name)

Factory for defining variables in requests. By default in functions arguments which are dicts all fields wrapped with double quoutes ". To specify members of variables defined above V factory should be used.

expect = 'MERGE({"user1": u.name}, {"user1": "name"})'
assert F.MERGE(
    {"user1": V("u.name")},
    {"user1": "name"}).build_query() == expect
class arango.aql.FuncFactory

AQL Function factory. This is F object in arango.aql module.

from arango.aql import F

c.test.query.over(F.PATH("a", "b", "c")).execute()

Execute query:

FOR obj IN PATH(a, b, c)
RETURN obj

Making raw queries with AQL

Now it’s possible to querieng database by using Arango Query Language (AQL).

This functionality implementation based on HTTP Interface for AQL Query Cursors and provide lazy iterator over dataset and with ability to customize (wrap) result item by custom wrapper.

Alternative way to do such king of functionality is by using Documents REST Api which is not implemented in driver.

class arango.cursor.Cursor(connection, query, count=True, batchSize=None, bindVars=None, wrapper=<bound method type.load of <class 'arango.document.Document'>>)

Work with Cursors in ArangoDB. At the moment, it’s common routine to work with AQL from this driver.

Note

the server will also destroy abandoned cursors automatically after a certain server-controlled timeout to avoid resource leakage.

  • query - contains the query string to be executed (mandatory)
  • count - boolean flag that indicates whether the
    number of documents found should be returned as “count” attribute in the result set (optional). Calculating the “count” attribute might have a performance penalty for some queries so this option is turned off by default.
  • batchSize - maximum number of result documents to be
    transferred from the server to the client in one roundtrip (optional). If this attribute is not set, a server-controlled default value will be used.
  • bindVars - key/value list of bind parameters (optional).
  • wrapper - by default it’s Document.load
    class, wrap result into
bind(bind_vars)

Bind variables to the cursor

first

Get first element from resultset

last

Return last element from current bulk. It’s NOT last result in entire dataset.

Custom data wrapper for raw queries

It’s not necessary to wrap all documents within Document object. Cursor do it by default but you can provide custom wrapper by overriding wrapper argument during execution of connection.query method.

Note

Also it’s possible to provide custom wrapper via arango.aql.AQLQuery.cursor method during building of the AQL query:

c.test1.query.cursor(wrapper=lambda conn, item: item)
             .filter("obj.name == 'John'").build_query()

wrapper should accept two arguments:

  • connection - first argument, current connection instnace
  • item - dictionary with data provided from ArangoDB query
from arango import c

wrapper = lambda conn, item: item

c.collection.test.create()
c.collection.test.documents.create({"1": 2})

# create connection to database
for item in c.query("FOR d in test RETURN d", wrapper=wrapper):
    item