Search code examples
node.jsarangodbarangojs

Error when using collection names as variables in ArangoDb with arangojs and aqlQuery


I've been arangojs for a few months and recently had some of my code start failing that used to work, regarding the use of variables as collection names when using template strings and aqlQuery.

I'm using Node.js 4.4.0 on Windows 10.

This example code shows the error:

// Issue with template string and arangodb with collection names
var arango = require('arangojs');
var aqlQuery = require('arangojs').aqlQuery;
var db = new arango('http://127.0.0.1:8529');

var collectionName = 'sampleCollection';

// Connect to _system
db.useDatabase('_system');

var sampleText = "Testing Only";

/* Add a record to the collection, using template string with collectionName
 * If I use ${collectionName} I get the error code 400:
 * error: 'bind parameter \'bind parameter \'value1\' has an invalid value or type near 
 * \'RETURN NEW._key\n
 * \' at position 4:9\' has an invalid value or type (while parsing)',
 *
 * If I write out the collection name, or use a normal db.query style query without using 
 * aqlQuery and template strings and pass the table name as @collectionName, then it works
 * fine.
 */
db.query(aqlQuery`
    INSERT { "something": ${sampleText} }
    IN ${collectionName}
    RETURN NEW._key
`).then(cursor =>
  cursor.all()
).then(vals => {
  console.log(`Created a new document with a _key of ${vals[0]}`)
}).catch(err => {
  console.log(err)
});

I've tested this on a clean npm install with only arangojs 4.3.0 and either Node 4.4.0 or Node 5.5.0 (using nodist).

Has anyone else seen issues with collection names in template strings?


Solution

  • The arangojs documentation doesn't explicitly point this out and the AQL documentation glosses over this, but collection bind variables are treated specially. When writing AQL queries by hand this means you need to prefix their names with an @ in the bindVars and accordingly reference them with a @@ prefix instead of the usual @.

    Because there's no way to recognize whether a string refers to a string value or the name of a collection, the correct way to use collections as bind variables in aqlQuery is to pass in an arangojs collection object instead of the string itself, e.g.:

    const collection = db.collection(collectionName);
    db.query(aqlQuery`
      INSERT { "something": ${sampleText} }
      IN ${collection}
      RETURN NEW._key
    `)
    

    If you log the output of the aqlQuery template to the console you will see that the query correctly inserts a reference with the @@ prefix and bind variables contains the @ prefixed variable with its value being the name of the collection (rather than the collection object you passed in).