6

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

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

Activity 1

Activity 2

Grouped Activity
  Activity 3
  Activity 4

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

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

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

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

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

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

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

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

我的另一种方法是为每个提要结果分配一个递增的数字。由于数字是按顺序递增的,如果缺少数字/id,我可以选择下一个。但是,这样做的问题是,如果我开始在提要中间删除和添加提要项目,则光标 ID 会发生变化。我必须解决这个问题的一个解决方案是在每个数字之间有一个巨大的差距,但是很难确定如何以确定的方式将新项目添加到每个数字之间的空间中。此外,随着新项目的添加,以及正在填补的空白,我们最终会遇到同样的问题。

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

4

1 回答 1

2

您需要有额外的(或现有的)列,为目标表的每个新添加行顺序增加。我们将此列称为 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

回复:

{
    "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}

引擎盖下发生了什么:

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

或向后光标:

GET /api/v1/items?size={count}&cursor=fw_{prevFieldName}_{prevId}

引擎盖下发生了什么:

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

响应将与上一个类似

于 2018-07-12T12:01:35.050 回答