如果使用数组,以下查询将不起作用,但如果使用字符串构造代码段,则以下查询将正常工作。我是在某个地方犯了错误还是这是与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}"`)
答案 0 :(得分:1)
FILTER u.id IN "${array}"
产生FILTER u.id IN "1,2"
。请注意,IN
右侧是一个字符串,不再是字符串数组。
发生的事情是,字符串插值(反引号)使用了array.toString()
的结果,即1,2
。周围的引号实际上是被接管的,这可能不是您想要的。请参见Queries docs for 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()的调用再次将其解包。通常,aql
帮助程序在内部调用toAQL()。
> 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'
但是,这不是很优雅,从ArangoJS v6.7.0开始,它实际上支持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
`)
您也可以通过ArangoDB v3.4在Arangosh / Foxx(db._query()
)中使用它。
另请参阅:ArangoJS Changelog