【问题标题】:ArangoDB - Sort result in aql with custom functionArangoDB - 使用自定义函数对 aql 中的结果进行排序
【发布时间】:2017-08-11 12:41:36
【问题描述】:

我希望根据用户输入对结果进行排序。

假设我有可能看起来像这样的sort 对象:

var sort = {createdAt: -1}

或者像这样:

var sort = {createdAt: 1, name: 1}

我的查询看起来像这样:

FOR f in [{createdAt: 123, name: 'BBB'},{createdAt: 2000, name: 'ZZZ'}, {createdAt: 2000, name: 'BBB'}]
    SORT f.createdAt DESC
    RETURN f

它工作正常。 但我想按用户在排序对象中传递的字段对结果进行排序。 我添加了自定义 arango 函数:

db.createFunction(
    'CUSTOM::FILTERING::SORT_STRING',
            String(function (sort, it) {
                    return sort && Object.keys(sort).length !== 0 && sort.constructor === Object ? Object.keys(sort).map(key => `${it}.${key} ${sort[key] >= 0 ? 'ASC' : 'DESC'}`).join(', ') : '';
            })
        );

但是当我以这种方式使用它时,它根本不起作用。结果未以任何方式排序:

FOR f in [{createdAt: 123, name: 'BBB'},{createdAt: 2000, name: 'ZZZ'}, {createdAt: 2000, name: 'BBB'}]
    SORT CUSTOM::FILTERING::SORT_STRING(${sort}, 'f')
    RETURN f

如何根据不同的输入参数对结果进行排序?

【问题讨论】:

  • 您看过 ArangoDB 中的 Foxx 微服务吗?这是他们的完美应用,让 Foxx 呈现一个 REST API,然后用户可以提供 Sort、PageNum、PageSize、Query 属性,Foxx REST API 会为您完成。
  • @DavidThomas 你能给我一些实现它的例子吗?
  • 查看this answer,我在其中提供了一个示例,说明如何设置 Foxx 微服务以响应 REST API 请求。您可以允许调用者通过路径、查询字符串或正文提供额外的查询参数,然后让您的代码调用适当的查询。如何编写 Foxx 微服务超出了这个问题的范围,但它遵循 Node.js 样式格式,网上有很多例子,尤其是在 github.com。
  • @DavidThomas 不幸的是 Foxx 不适合我。有没有办法用自定义函数做到这一点?
  • 他们正在远离 UDF,偏爱 Foxx。很抱歉听到 Foxx 不能为您工作,我无法从纯自定义功能的角度回答您的问题。我使用 Foxx 微服务来做到这一点。

标签: javascript node.js arangodb aql


【解决方案1】:

纯 AQL,您可以这样做,但在世界某个地方,一只小狗会死去......

RETURN (@sortBy == 'createdAt' ?
  (FOR d IN @@collectionName
    SORT createdAt DESC
    RETURN d) : (@sortBy == 'name' ?
      (FOR d in @@collectionname
        SORT name DESC
        RETURN d)
    )
  )
)

但另一种方法是动态生成 AQL,通过适当的代码检查,您可以安全地进行。

我有时会动态生成 AQL,但所有参数都经过仔细扫描、清理、Joi 模式校对和验证以停止 SQL 注入。

进行这种样式查询的另一种方式是:

LET sortByCreatedAt = (
  FOR d in @@collectionName
    SORT createdAt DESC
    RETURN d)

LET sortByName = (
  FOR d in @@collectionName
    SORT name DESC
    RETURN d)

RETURN (@sortBy == 'createdAt') ? sortByCreatedAt : sortByName

这不是很漂亮,但很有效,并且您可以通过创造力编写大量嵌套和复杂的查询,并使用 ASC 和 DESC 作为选项以及预定义数量的列名。重要的是,列名不能完全动态,但可以由用户选择。

我没有在 ArangoDB 服务器上测试过这些,所以可能存在一些拼写错误。

【讨论】:

  • 我不能动态地做到这一点。我有时需要按名称和 createdAt 字段排序,有时只需要按 createdAt 排序。排列太多,无法分别编写每个案例。我还想在其他查询中重用它。我可以编写动态创建此类字符串的函数,但是在调用 db 查询时我不能使用 js aql 标签。很遗憾,没有简单的方法可以用 arango 进行排序:(
  • 排序很简单.. 发送之前不能使用 Foxx 或动态生成 AQL 有什么原因吗?
  • 由于客户限制,我无法使用 Foxx。并且动态生成的 AQL 不适用于 js aql 标签。由于安全限制,它失败了。我不想接受注射。如果我自己进行验证,总是有可能错过重要的事情。
  • 你试过类似for d in @@collection sort d.@mysort @direction return d的东西吗? @mysort 是您的排序键,@direction 是 'asc' 或 'desc'
  • 是的。如果有固定数量的字段要排序,它就可以工作。但是,如果我有不同数量的字段要排序并且方向不同,它就不起作用:(
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-08-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多