【问题标题】:Cursor Based Pagination for search results without sequential unique ids (eg. location)没有顺序唯一ID(例如位置)的搜索结果的基于光​​标的分页
【发布时间】:2019-12-07 10:33:49
【问题描述】:

我正在尝试为用户可以按位置(lat、lng)搜索和排序的数据实现基于光标的分页。一个简化的示例是假设一个名为“可搜索”的实体。它将有其唯一的主键“id”字段和位置字段“lat”、“lng”。

在我按照与特定点的距离排序后,'id's 会乱七八糟。似乎没有唯一的顺序 id 可用作游标。我也不能使用“lat”和“lng”,因为搜索和排序是按半径/距离,这意味着“lat”和“lng”也没有顺序。

这是否意味着基于游标的分页不适合此类查询?或者有什么方法可以为这种情况实现游标?

【问题讨论】:

    标签: pagination


    【解决方案1】:

    我认为即使在这种情况下你也可以实现基于光标的分页。

    首先,您说您的结果是按与某个点的距离排序的。我假设它是用户可以指定的某个起点的距离(比如要求地图应用程序“显示我附近的餐馆”)。在这种情况下,游标值不是静态的,不能存储在您的可搜索记录中。它必须根据用户输入来计算。通过即时计算游标,您将失去游标分页 [1] 的优势之一 - 对大型结果集具有良好的有效性。这是因为您不能简单地使用数据库索引来跳过游标值“低于”指定值的记录。

    [1] 有关光标分页的优缺点的更多信息,请参阅 Slack 工程师的这篇文章:https://slack.engineering/evolving-api-pagination-at-slack-1c1f644f8e12

    其次,距离本身可能不足以进行明确的排序,因为两个不同的可搜索可能与起点的距离相同。为了解决这个问题,您可以将 ID 添加为辅助排序字段,这将使顺序具有​​确定性(或数学术语中的 total order)。

    距离和 ID 一起形成一个可以用作光标的值。

    例如,假设当前页面上的最后一个结果的距离为 123.45 公里(或您使用的任何单位)并且 ID 为 98765。

    这将转换为以下光标:

    {
        distance: 123.45,
        id: 98765
    }
    

    当您想“转到下一页”时,您只需使用此光标在 可搜索 之后请求 10 个(或您的页面大小)可搜索

    如果你熟悉 SQL,它会转化为这样的查询:

    SELECT s.*
    FROM searchables s
    WHERE get_distance(stating_point, s) > 123.45
        OR get_distance(stating_point, s) = 123.45 AND s.id > 98765
    LIMIT 10
    

    其中get_distance(a, b) 函数计算点ab 之间的距离。

    实际上,如果距离和 ID 都可以在某个范围内限定,您可以使用巧妙的技巧并将光标编码为单个字符串,其字典顺序将对应于结果的顺序 - 例如。 “0000000123.4500-0000098765”。

    这样SQL查询可以简化为:

    SELECT s.*
    FROM searchables s
    WHERE get_cursor(get_distance(stating_point, s), s.id) > '0000000123.4500-0000098765'
    LIMIT 10
    

    get_cursor(distance, id) 函数将距离和 ID 格式化为建议格式的字符串。

    【讨论】:

      猜你喜欢
      • 2020-06-04
      • 2012-11-15
      • 2020-12-30
      • 1970-01-01
      • 1970-01-01
      • 2013-03-15
      • 2021-04-09
      • 2018-11-30
      • 1970-01-01
      相关资源
      最近更新 更多