【问题标题】:AQL template in arango Foxx does not work correctly with arrayarango Foxx 中的 AQL 模板无法与数组一起正常工作
【发布时间】:2018-10-24 11:26:44
【问题描述】:

如果我使用数组,下面的查询将无法工作,但如果我们使用字符串来构造 sn-p,则可以正常工作。我是不是在某个地方弄错了,还是这个是与 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}"`)

【问题讨论】:

    标签: arrays templates ecmascript-6 arangodb foxx


    【解决方案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() 的调用再次将其解包。 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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-02-26
      相关资源
      最近更新 更多