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() 的调用再次将其解包。 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'
然而,这不是很优雅,从 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