我喜欢一些一些帮助处理一个奇怪的边缘情况与分页API我正在建设。

与许多api一样,这个api也会分页较大的结果。如果你查询/foos,你会得到100个结果(即foo #1-100),和一个链接到/foos?Page =2,返回foo #101-200。

不幸的是,如果在API使用者进行下一次查询之前从数据集中删除了foo #10, /foos?Page =2将偏移100并返回foos #102-201。

这对于试图获取所有foo的API使用者来说是一个问题——他们不会收到foo #101。

处理这种情况的最佳实践是什么?我们希望使它尽可能的轻量级(即避免为API请求处理会话)。来自其他api的示例将非常感谢!


当前回答

分页通常是一个“用户”操作,为了防止计算机和人脑的过载,通常会给出一个子集。然而,与其认为我们没有得到完整的列表,不如问问它重要吗?

如果需要一个精确的实时滚动视图,本质上是请求/响应的REST api并不适合这个目的。为此,你应该考虑WebSockets或HTML5 Server-Sent Events,让你的前端知道何时处理更改。

现在,如果需要获得数据的快照,我将只提供一个API调用,在一个请求中提供所有数据,而不进行分页。请注意,如果您有一个大型数据集,您将需要一些可以执行输出流而不临时将其加载到内存中的东西。

对于我的例子,我隐式地指定了一些API调用来允许获取全部信息(主要是引用表数据)。您还可以保护这些api,使其不会损害您的系统。

其他回答

分页通常是一个“用户”操作,为了防止计算机和人脑的过载,通常会给出一个子集。然而,与其认为我们没有得到完整的列表,不如问问它重要吗?

如果需要一个精确的实时滚动视图,本质上是请求/响应的REST api并不适合这个目的。为此,你应该考虑WebSockets或HTML5 Server-Sent Events,让你的前端知道何时处理更改。

现在,如果需要获得数据的快照,我将只提供一个API调用,在一个请求中提供所有数据,而不进行分页。请注意,如果您有一个大型数据集,您将需要一些可以执行输出流而不临时将其加载到内存中的东西。

对于我的例子,我隐式地指定了一些API调用来允许获取全部信息(主要是引用表数据)。您还可以保护这些api,使其不会损害您的系统。

RESTFul api中的另一个分页选项是使用这里介绍的Link头。例如,Github使用它如下:

Link: <https://api.github.com/user/repos?page=3&per_page=100>; rel="next",
  <https://api.github.com/user/repos?page=50&per_page=100>; rel="last"

rel的可能值是:first, last, next, previous。但是通过使用Link头,可能无法指定total_count(元素的总数)。

可能很难找到最佳实践,因为大多数带有api的系统都不适应这种情况,因为这是一个极端的优势,或者它们通常不会删除记录(Facebook, Twitter)。Facebook实际上表示,由于分页后进行了过滤,每个“页面”可能没有请求的结果数量。 https://developers.facebook.com/blog/post/478/

如果你真的需要适应这种边缘情况,你需要“记住”你停止的地方。jandjorgensen的建议是正确的,但我将使用保证唯一的字段,如主键。您可能需要使用多个字段。

按照Facebook的流程,您可以(也应该)缓存已经请求的页面,如果它们请求已经请求过的页面,则只返回已删除的行。

我认为目前你的api的反应应该是这样的。页面上的前100条记录按照您所维护的对象的总体顺序排列。您的解释告诉我们,您正在使用某种排序id来定义分页对象的顺序。

现在,如果您希望第2页始终从101开始,到200结束,那么您必须将该页上的条目数量作为变量,因为它们可能会被删除。

你应该做如下的伪代码:

page_max = 100
def get_page_results(page_no) :

    start = (page_no - 1) * page_max + 1
    end = page_no * page_max

    return fetch_results_by_id_between(start, end)

再补充一下Kamilk的回答:https://www.stackoverflow.com/a/13905589

这在很大程度上取决于你处理的数据集有多大。小型数据集确实可以有效地进行偏移分页,但大型实时数据集确实需要游标分页。 找到了一篇精彩的文章,关于Slack如何随着数据集的增加而进化其api的分页,解释了每个阶段的积极和消极因素:https://slack.engineering/evolving-api-pagination-at-slack-1c1f644f8e12