F21*_*F21 5 pagination cursor cursor-position
我有活动存储在图形数据库中.在某些情况下,多个活动被分组并聚合为1个活动.
已处理的活动Feed可能如下所示:
Activity 1
Activity 2
Grouped Activity
Activity 3
Activity 4
Activity 5
Run Code Online (Sandbox Code Playgroud)
活动具有更新的时间戳和唯一ID.
活动按其更新时间排序,如果是分组活动,则使用其子活动中的最新更新时间.
活动可以插入列表中的任何位置(例如,如果我们开始关注某人,他们过去的活动将被插入到列表中).
可以从列表中的任何位置删除活动.
由于数据量大,使用带有微秒的时间戳仍然可能导致冲突(2个项目可以具有相同的时间戳).
游标标识符应该是唯一且稳定的.添加和删除Feed项不应更改标识符.
我想介绍基于光标的分页,以允许客户端通过类似于twitter的 Feed分页.似乎没有太多关于它们是如何构建的信息,因为我只发现这篇博文在谈论实现它们.但是,如果光标的标识符恰好指向已删除的项目,则似乎存在问题.
有了上述内容,我如何生成一个可用作上述光标的标识符?最初,我考虑将时间戳与唯一ID组合:1371813798111111.myuniqueid.但是,如果1371813798111111.myuniqueid删除了项目,我可以获取带有1371813798111111时间戳的项目,但无法确定哪个项目应该以我应该开始的时间戳.
我的另一种方法是为每个Feed结果分配一个递增的数字.由于数字是递增的并且按顺序,如果缺少数字/ id,我可以选择下一个.但是,这样做的问题是,如果我开始在Feed中间删除并添加Feed项,则游标ID会发生变化.我遇到这个问题的一个解决方案是每个数字之间存在巨大差距,但很难确定如何以确定的方式将新项目添加到每个数字之间的空间.此外,随着新项目的增加,以及填补的空白,我们最终会遇到同样的问题.
简单地说,如果我有一个项目列表,可以在列表中的任何位置添加和删除项目,那么为每个列表项生成id的最佳方法是,如果删除了id的项目,我仍然可以确定它在列表中的位置?
小智 2
您需要有额外的(或现有的)列,该列对于目标表中每个新添加的行依次增加。我们将此列称为seq_id。
当客户端第一次请求游标时:
GET /api/v1/items?sort_by={sortingFieldName}&size={count}
Run Code Online (Sandbox Code Playgroud)
其中 sortingFieldName 是我们应用排序的字段名称
幕后发生了什么:
SELECT * FROM items
WHERE ... // apply search params
ORDER BY sortingFieldName, seq_id
LIMIT :count
Run Code Online (Sandbox Code Playgroud)
回复:
{
"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}"
}
}
Run Code Online (Sandbox Code Playgroud)
如果我们检索的行数少于 count 行,则游标的下一个将不会出现在响应中。
如果请求中没有游标或没有要返回的数据,游标的前一部分将不会出现在响应中。
当客户端再次执行请求时 - 他需要使用游标。向前光标:
GET /api/v1/items?size={count}&cursor=fw_{nextFieldName}_{nextId}
Run Code Online (Sandbox Code Playgroud)
幕后发生了什么:
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
Run Code Online (Sandbox Code Playgroud)
或向后光标:
GET /api/v1/items?size={count}&cursor=fw_{prevFieldName}_{prevId}
Run Code Online (Sandbox Code Playgroud)
幕后发生了什么:
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
Run Code Online (Sandbox Code Playgroud)
响应将与前一个类似