【问题标题】:ArangoDB custom sort orderArangoDB 自定义排序顺序
【发布时间】:2015-05-11 17:57:21
【问题描述】:

我想按特定顺序对字段进行排序,比如说 2、4、1、5、3。

在 MySQL 中,我可以使用 ORDER BY FIELD(id,2,4,1,5,3)

ArangoDB 有什么等价物吗?

【问题讨论】:

    标签: mysql arangodb aql nosql


    【解决方案1】:

    我认为应该可以使用POSITION AQL 函数,它可以返回一个元素在数组中的位置

    FOR i IN [ 1, 2, 3, 4, 5 ]                  /* what to iterate over */
      SORT POSITION([ 2, 4, 1, 5, 3 ], i, true) /* order to be returned */
      RETURN i
    

    这将返回:

    [ 2, 4, 1, 5, 3 ]
    

    更新:我原来的答案包括CONTAINS AQL 函数,但是,它应该是POSITION

    【讨论】:

    • 当然,是的,POSITION() 更容易使用。但是,我认为它并不直接等同于 OP 功能,因为它只以定义的顺序返回定义的值。之后它不会返回结果集的其余值,正如 MYSQL 功能所建议的那样。但是,它会很好地取代我建议的第一部分。 :)
    • 用以下方法测试它: POSITION ([1,5,3],i,true) 返回 [ 2, 4, 1, 5, 3 ] 这不是想要的结果,除非定义了为结果集中的每个可能值给出排序顺序。
    • 如果元素不在比较值列表中,MySQL 的 FIELD 不返回 0 吗? AQL 的POSITION 类似:如果值不包含在搜索数组中,它将返回-1。 MySQL 将返回从 1 开始的位置,而 AQL 将返回从 0 开始的位置,但这不应该影响结果的顺序。在 MySQL 和 AQL 中,未包含在搜索列表/数组中的项目的内部顺序是未定义的,但如果这很重要,也可以添加辅助搜索条件来对它们进行排序,例如SORT POSITION([ 2, 4, 1, 5, 3 ], i, true), i ASC.
    • @stj 谢谢,POSITION() 似乎正是我所需要的,我也可以将它用于我遇到问题的其他类似事情。 @thesilentman 如果您希望不在列表中的元素排在按列表排序的元素之后,您还可以使用 DESC 排序并反转列表。
    【解决方案2】:

    不幸的是,目前还没有直接的等价物。

    但是,有一些方法可以自己完成。

    1) 通过构造 AQL 查询: 该查询将通过您的排序值数组运行,并为每个定义的值查询数据库。然后将这些结果中的每一个添加到最终的输出数组中。

    请注意,这确实会降低性能,因为每个值都有一个查询。如果您只定义几个,我想这是可以容忍的,但如果您必须定义例如几十个或几百个,它将导致 n+1 个查询(其中 n 是自定义排序值的数量)。

    “+1”是最后一个查询,它应该得到所有其他值的结果,这些值未在您的自定义排序数组中定义,并将这些附加到您的输出数组。

    这看起来像下面的 sn-p,您可以将其复制到 AQL 编辑器中并运行它。

    sn-p 的注意事项:

    • 我首先创建一个数组,它代表我们的集合 会查询。
    • 然后我正在设置定义的排序值。
    • 之后,实际的 AQL 语句就开始工作了。
    • 另外,请注意外部 RETURN 语句中的 FLATTEN 函数,这是必需的,因为在第一个循环中,我们为每个定义的排序值获取结果数组。这些都必须扁平化到同一级别,以便作为唯一的结果集(而不是许多封装的小结果集)进行处理。

    /* Define a dummy collection-array to work with */
    LET a = [
      {
    "_id": "a/384072353674",
    "_key": "384072353674",
    "_rev": "384073795466",
    "sort": 2
      },
      {
    "_id": "a/384075040650",
    "_key": "384075040650",
    "_rev": "384075827082",
    "sort": 3
      },
      {
    "_id": "a/384077137802",
    "_key": "384077137802",
    "_rev": "384078579594",
    "sort": 4
      },
      {
    "_id": "a/384067504010",
    "_key": "384067504010",
    "_rev": "384069732234",
    "sort": 1
      },
      {
    "_id": "a/384079497098",
    "_key": "384079497098",
    "_rev": "384081004426",
    "sort": 5
      }
    ]
    
    /* Define the custom sort values */
    LET cSort = [5,3,1]
    
    /* Gather the results of each defined sort value query into definedSortResults */
    LET definedSortResults = (
    FOR u in cSort
        LET d = (
        FOR docs IN `a` 
            FILTER docs.`sort` == u
            RETURN docs
        )
        RETURN d
    )
    
    /* Append the the result of the last (all the non-defined sort values) query to the results of the definedSortResults into the output array */
    LET output = (
    APPEND (definedSortResults, (
        FOR docs IN `a` 
                FILTER docs.`sort` NOT IN cSort
                RETURN docs
        )
    )
    )
    
    /* Finally FLATTEN and RETURN the output variable */
    RETURN FLATTEN(output)

    2) 一种不同的方法是,使用 JavaScript 编写的函数扩展 AQL,它基本上会执行与上述相同的步骤。

    当然,您也可以在 ArangoDB 的 GitHub 页面上提出功能请求,也许 ArangoDB 的好人会考虑将其包含在内。 :)

    希望有帮助

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-05-12
      • 2016-05-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-04-02
      • 1970-01-01
      相关资源
      最近更新 更多