J@ArangoDB

{ "subject" : "ArangoDB", "tags": [ "multi-model", "nosql", "database" ] }

On Building AQL Query Strings

I recently wrote two recipes about generating AQL query strings. They are contained in the ArangoDB cookbook by now:

After that, Github user tracker1 suggested in Github issue 1457 to take the ES6 template string variant even further, using a generator function for string building, and also using promises and ES7 async/await.

We can’t use ES7 async/await in ArangoDB at the moment due to lacking support in V8, but the suggested template string generator function seemed to be an obvious improvement that deserved inclusion in ArangoDB.

Basically, the suggestion is to use regular JavaScript variables/expressions in the template string and have them substituted safely.

With regular AQL bind parameters, a query looks like this:

1
2
3
4
5
var bindVars = { name: "test" };
var query = `FOR doc IN collection
             FILTER doc.name == @name
             RETURN doc._key`;
db._query(query, bindVars);

This is immune to parameter injection, because the query string and the bind parameter value are passed in separately. But it’s not very ES6-y.

Now, after partly implementing tracker1’s suggestion, JavaScript values and expressions can be used much more naturally when building AQL query strings:

1
2
3
4
5
var name = "test";
var query = aqlQuery`FOR doc IN collection
                     FILTER doc.name == ${name}
                     RETURN doc._key`;
db._query(query);

${name} is regular ES template string syntax and would normally be substituted with the value of JavaScript variable name. Such simple substitution would be unsafe, because it would make the query vulnerable to parameter injection. So we’re also using a template string generator function named aqlQuery. This function comes bundled with ArangoDB 2.7.

Under the hood, aqlQuery will create regular AQL bind parameters for each occurrence of a template string parameter. It will keep the query string and the actual bind parameter values separate, so it is safe to use.

The function will return an object with that can directly be passed on to the db._query() function. Here’s what aqlQuery will generate for the above example (note: some whitespace was removed from the output):

1
2
3
4
5
6
{
  "query" : "FOR doc IN collection FILTER doc.name == @value0 RETURN doc._key",
  "bindVars" : {
    "value0" : "test"
  }
}

The aqlQuery template string generator function is available in 2.7, which is currently in development. The changes are contained in the devel branch only at the moment, but will become available in following 2.7 release. A pull request has been issued to have the cookbook recipes updated to include aqlQuery, too.

aqlQuery can be used in 2.7 from the ArangoShell, inside arangod (e.g. from inside Foxx actions) and from ArangoDB’s web interface.

All other variants for building AQL queries are still fully supported.