Шаблон AQL в arango Foxx не работает корректно с массивом - PullRequest
0 голосов
/ 24 октября 2018

Следующий запрос не будет работать, если я использую массив, но будет работать нормально, если мы используем строку для создания фрагмента.Я где-то допустил ошибку или это ошибка, связанная с arango?

var array=["1","2"]
//Make a snippet depend on array.
var snippet=aql.literal(`FILTER u.id IN "${array}"`)

//Main query. Result is incorrect even though it runs
var query=db._query(aql`
For u in Collection
{$snippet}
RETURN u
`
)

Пример правильного запроса с использованием строки

var string="1"
var snippet=aql.literal(`FILTER u.id == "${array}"`)

1 Ответ

0 голосов
/ 24 октября 2018

FILTER u.id IN "${array}" производит FILTER u.id IN "1,2".Обратите внимание, что справа от IN находится строка, а не массив строк.

В результате интерполяция строки (обратные метки) использует результат array.toString(), чтоэто 1,2.Окружающие кавычки взяты буквально, что, вероятно, не то, что вы хотите.См. Пример в самом конце Запроса документов для ArangoJS .

Даже если представление массива было ["1","2"], тогда эти кавычки приведут к "["1","2"]", что даст вамошибка синтаксиса.Если экранировать внутренние кавычки, как "[\"1\",\"2\"]", вы бы протестировали u.id IN "some string", но оператор IN вернет false для любой строки справа (вам нужен массив здесь).

RETURN "1" IN "1"       // false
RETURN "1" IN "[\"1\"]" // false
RETURN "1" IN ["1"]     // true

Давайте попробуем по-разному использовать aql.literal:

> aql.literal(`FILTER u.id IN ${array}`).toAQL()
'FILTER u.id IN 1,2'

Существует шаблонный литерал, который оценивается , а затем передается в качестве аргумента функции.Функция просто оборачивает строку, созданную литералом шаблона, и вызов toAQL () разворачивает ее снова.toAQL () обычно вызывается внутренне помощником aql.

> aql.literal`FILTER u.id IN ${array}`.toAQL()
'FILTER u.id IN ,'

При этом используется aql.literal для тегового шаблона, но он не предназначен для того, чтобы быть функцией для обработки строк шаблона.Вывод бесполезен.

> aql.literal('FILTER u.id IN ${array}').toAQL()
'FILTER u.id IN ${array}'

Строка в кавычках (без литерала шаблона!) Передается в качестве аргумента aql.literal.Результат идентичен вводу со знаком доллара и фигурными скобками.Это буквально так же, как ввод.Это предполагаемый способ использования aql.literal(). не поддерживает параметры связывания .

Вы можете положиться на JSON.stringify(), чтобы корректно экранировать массив следующим образом:

> aql.literal('FILTER u.id IN ' + JSON.stringify(array)).toAQL()
'FILTER u.id IN ["1","2"]'

Пример использования:

> var snippet = aql.literal('FILTER u.id IN ' + JSON.stringify(array))
> aql`FOR u IN Collection ${snippet} RETURN u`.query
'FOR u IN Collection FILTER u.id IN ["1","2"] RETURN u'

Однако, это не очень изящно, и начиная с v6.7.0 ArangoJS, он фактически поддерживает вложение aql литералов шаблона:

>var snippet = aql`FILTER u.id IN ${array}`

>snippet // see what happens under the hood
{ query: 'FILTER u.id IN @value0',  // a bind parameter is used!
  bindVars: { value0: [ '1', '2' ] },
  _source: [Function: _source] }

> aql`FOR u IN Collection ${snippet} RETURN u`

{ query: 'FOR u IN Collection FILTER u.id IN @value0 RETURN u',
  bindVars: { value0: [ '1', '2' ] }, // still bind parameter with the snippet integrated!
  _source: [Function: _source] }

Пример использования (для ArangoJS):

var array = [ "1", "2" ]
var snippet = aql`FILTER u.id IN ${array}`
var query = db.query(aql`
  FOR u IN Collection
    ${snippet}
    RETURN u
`)

Вы также сможете использовать его в Arangosh / Foxx (db._query()) с ArangoDB v3.4.

Также см .: ArangoJS Changelog

...