Pagination 构建分页游标

Pagination 构建分页游标,pagination,cursor,cursor-position,Pagination,Cursor,Cursor Position,我有存储在图形数据库中的活动。在某些情况下,多个活动被分组并聚合为一个活动 已处理的活动提要可能如下所示: Activity 1 Activity 2 Grouped Activity Activity 3 Activity 4 Activity 5 活动具有更新的时间戳和唯一id 活动按其更新时间排序,如果是分组活动,则使用其子活动中最近更新的时间 活动可以插入列表中的任何位置(例如,如果我们开始跟踪某人,他们过去的活动将插入列表) 可以从列表中的任何位置删除活动 由于数据量

我有存储在图形数据库中的活动。在某些情况下,多个活动被分组并聚合为一个活动

已处理的活动提要可能如下所示:

Activity 1

Activity 2

Grouped Activity
  Activity 3
  Activity 4

Activity 5
  • 活动具有更新的时间戳和唯一id

  • 活动按其更新时间排序,如果是分组活动,则使用其子活动中最近更新的时间

  • 活动可以插入列表中的任何位置(例如,如果我们开始跟踪某人,他们过去的活动将插入列表)

  • 可以从列表中的任何位置删除活动

  • 由于数据量大,使用微秒的时间戳仍然可能导致冲突(2个项目可能具有相同的时间戳)

  • 光标标识符应该是唯一且稳定的。添加和删除提要项不应更改标识符

我想介绍基于光标的分页,以允许客户端通过类似于的提要分页。关于它们是如何构建的,似乎没有太多的信息,因为我只发现这是在谈论如何实现它们。但是,如果光标的标识符恰好指向已删除的项,则似乎有问题

有了以上内容,我如何生成一个标识符,可以用作上述内容的游标?最初,我考虑将时间戳与唯一id结合起来:
1371813798111111.myuniqueid
。但是,如果
1371813798111111.myuniqueid
处的项目被删除,我可以获得带有
1371813798111111
时间戳的项目,但无法确定应该从哪个带有该时间戳的项目开始

我的另一种方法是为每个提要结果分配一个递增的数字。由于该数字是递增的,并且是按顺序排列的,因此如果该数字/id丢失,我可以选择下一个。然而,问题是,如果我开始删除并在feed的中间添加进给项,游标ID就会改变。我对这个问题的一个解决方案是在每个数字之间有一个巨大的间隙,但很难确定如何以确定的方式将新项目添加到每个数字之间的空间中。此外,随着新项目的增加,以及缺口的填补,我们最终也会遇到同样的问题


简单地说,如果我有一个项目列表,可以从列表中的任何位置添加和删除项目,那么为每个列表项目生成id的最佳方法是什么,这样,如果id的项目被删除,我仍然可以确定其在列表中的位置。

您需要有其他(或现有)的项目为目标表中每个新添加的行顺序增加的列。让我们将此列称为seq_id

当客户端第一次请求游标时:

GET /api/v1/items?sort_by={sortingFieldName}&size={count}
其中sortingFieldName是应用排序的字段的名称

引擎盖下发生了什么:

SELECT * FROM items
WHERE ...            // apply search params
ORDER BY sortingFieldName, seq_id
LIMIT :count
SELECT * FROM items
WHERE ...            // apply search params
AND ((fieldName = :cursor.nextFieldName AND seq_id > :cursor.nextId) OR 
      fieldName > :cursor.nextFieldName)
ORDER BY sortingFieldName, seq_id
LIMIT :count
SELECT * FROM items
WHERE ...            // apply search params
AND ((fieldName = :cursor.prevFieldName AND seq_id < :cursor.prevId) OR 
      fieldName < :cursor.prevFieldName)
ORDER BY sortingFieldName DESC, seq_id DESC
LIMIT :count
答复:

{
    "data": [...],
    "cursor": {
        "prev_field_name": "{result[0].sortingFieldName}",
        "prev_id": "{result[0].seq_id}",
        "nextFieldName": "{result[count-1].sortingFieldName}",
        "next_id": "{result[count-1].seq_id}",
        "prev_results_link": "/api/v1/items?size={count}&cursor=bw_{prevFieldName}_{prevId}",
        "next_results_link": "/api/v1/items?size={count}&cursor=fw_{nextFieldName}_{nextId}"       
    }
}
若我们检索到的行数少于个,则下一个游标将不会出现在响应中

如果请求中没有游标或没有要返回的数据,则游标的上一部分将不会出现在响应中

当客户端再次执行请求时,他需要使用游标。前进光标:

GET /api/v1/items?size={count}&cursor=fw_{nextFieldName}_{nextId}
GET /api/v1/items?size={count}&cursor=fw_{prevFieldName}_{prevId}
引擎盖下发生了什么:

SELECT * FROM items
WHERE ...            // apply search params
ORDER BY sortingFieldName, seq_id
LIMIT :count
SELECT * FROM items
WHERE ...            // apply search params
AND ((fieldName = :cursor.nextFieldName AND seq_id > :cursor.nextId) OR 
      fieldName > :cursor.nextFieldName)
ORDER BY sortingFieldName, seq_id
LIMIT :count
SELECT * FROM items
WHERE ...            // apply search params
AND ((fieldName = :cursor.prevFieldName AND seq_id < :cursor.prevId) OR 
      fieldName < :cursor.prevFieldName)
ORDER BY sortingFieldName DESC, seq_id DESC
LIMIT :count
或向后光标:

GET /api/v1/items?size={count}&cursor=fw_{nextFieldName}_{nextId}
GET /api/v1/items?size={count}&cursor=fw_{prevFieldName}_{prevId}
引擎盖下发生了什么:

SELECT * FROM items
WHERE ...            // apply search params
ORDER BY sortingFieldName, seq_id
LIMIT :count
SELECT * FROM items
WHERE ...            // apply search params
AND ((fieldName = :cursor.nextFieldName AND seq_id > :cursor.nextId) OR 
      fieldName > :cursor.nextFieldName)
ORDER BY sortingFieldName, seq_id
LIMIT :count
SELECT * FROM items
WHERE ...            // apply search params
AND ((fieldName = :cursor.prevFieldName AND seq_id < :cursor.prevId) OR 
      fieldName < :cursor.prevFieldName)
ORDER BY sortingFieldName DESC, seq_id DESC
LIMIT :count
从项目中选择*
在哪里…//应用搜索参数
和((字段名=:cursor.prevFieldName和seq_id<:cursor.prevId)或
fieldName<:cursor.prevFieldName)
按排序的订单字段名称说明,序号id说明
限制:计数

响应将与前一个类似

您是否找到了解决方案,我有类似的用例,其中我必须显示多级列表。请参阅本文:使用向后光标时,您必须在返回结果之前还原结果,对吗?