arango Foxx中的AQL模板不适用于数组 [英] AQL template in arango Foxx does not work correctly with array

查看:94
本文介绍了arango Foxx中的AQL模板不适用于数组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果使用数组,以下查询将不起作用,但如果使用字符串构造代码段,则以下查询将正常工作.我是在某个地方犯了错误还是这是与arango相关的错误?

The below query would not work if I used an array but work normally if we use a string to construct the snippet. Did I make a mistake somewhere or is this one is a bug related to 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
`
)

使用字符串进行正确查询的示例

Example of the correct query using string

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

推荐答案

FILTER u.id IN "${array}"产生FILTER u.id IN "1,2".请注意,IN右侧是一个字符串,不再是字符串数组.

FILTER u.id IN "${array}" produces FILTER u.id IN "1,2". Note that what is on the right-hand side of IN is a string and not an array of strings anymore.

发生的情况是,字符串插值(反引号)使用了array.toString()的结果,即1,2.周围的引号实际上是被接管的,这可能不是您想要的.请参见 ArangoJS的查询文档.

What happens is that the string interpolation (backticks) uses the result of array.toString(), which is 1,2. The surrounding quote marks are taken over literally, which is probably not what you want. See an example at the very end of Queries docs for ArangoJS.

即使数组表示形式为["1","2"],这些引号也会导致"["1","2"]",这将给您带来语法错误.像"[\"1\",\"2\"]"那样使用内引号转义时,您将测试u.id IN "some string",但是IN运算符将为右侧的任何字符串返回 false (在这里需要一个数组).

Even if the array representation was ["1","2"], then these quotes would result in "["1","2"]", which would give you a syntax error. With the inner quote marks escaped like "[\"1\",\"2\"]" you would test u.id IN "some string", but the IN operator will return false for any string on the right-hand side (you need an array here).

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

让我们尝试使用不同的方法来使用aql.literal:

Let's try different ways to use aql.literal:

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

有一个模板文字,其值先进行评估,然后将作为参数传递给该函数.该函数仅包装由模板文字产生的字符串,并且对toAQL()的调用再次将其解包.通常,aql助手在内部调用toAQL().

There is a template literal which is evaluate and then passed as argument to the function. The function merely wraps the string produced by the template literal, and the call to toAQL() unwraps it again. toAQL() is normally called internally by the aql helper.

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

这将aql.literal用于标记的模板,但这并不意味着它是处理模板字符串的函数.输出没有用.

This uses aql.literal for a tagged template, but it is not meant to be a function to process template strings. The output is of no use.

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

带引号的字符串(无模板文字!)作为参数传递给aql.literal.结果与输入相同,带有一个美元符号和大括号.它实际上与输入相同.这是应使用aql.literal()的预期方式.它不支持绑定参数.

A string in quote marks (no template literal!) is passed as argument to aql.literal. The result is identical to the input, with a dollar sign and curly braces. It is literally the same as the input. This is the intended way how aql.literal() should be used. It does not support bind parameters.

您可以依靠JSON.stringify()正确地对数组进行转义,如下所示:

You could rely on JSON.stringify() to correctly escape the array like so:

> 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'

但是,这不是很优雅,从ArangoJS v6.7.0开始,它实际上支持aql模板文字的嵌套:

However, this isn't very graceful and from v6.7.0 of ArangoJS on, it actually supports nesting of aql template literals:

>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):

Usage example (for 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
`)

您也可以通过ArangoDB v3.4在Arangosh/Foxx(db._query())中使用它.

You will be able to use it in Arangosh/Foxx too (db._query()) with ArangoDB v3.4.

另请参阅: ArangoJS Changelog

这篇关于arango Foxx中的AQL模板不适用于数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆