我正在实现一个 RESTful API,它将订单公开为资源并支持通过结果集进行分页:
GET /orders?start=1&end=30
其中要分页的订单按
ordered_at
排序时间戳,降序。这基本上是来自 SO 问题的方法 #1 Pagination in a REST web application .如果用户请求第二页订单(
GET /orders?start=31&end=60
),服务器只需重新查询订单表,按 ordered_at DESC
排序。再次返回位置 31 到 60 中的记录。我遇到的问题是:如果在用户查看记录时结果集发生变化(例如添加了新订单),会发生什么?在添加新订单的情况下,用户会在结果的第二页上的第一个位置看到旧订单 #30(因为相同的订单现在是 #31)。更糟糕的是,在删除的情况下,用户会在第二页 (#31) 的第一个位置看到旧订单 #32,而根本看不到旧订单 #31(现在是 #30)。
如果不以某种方式使 RESTful 服务器有状态(urg)或在每个客户端中构建一些分页智能,我就看不到解决方案......有哪些既定技术可以处理这个问题?
为了完整性:我的后端是在 Scala/Spray/Squeryl/Postgres 中实现的;我正在构建两个前端客户端,一个在backbone.js 中,另一个在Python Django 中。
最佳答案
我这样做的方法是使索引从旧到新。所以他们永远不会改变。然后在没有任何开始参数的情况下查询时,返回最新的页面。此外,响应应包含一个指示包含哪些元素的索引,以便您可以计算需要为下一个旧页面请求的索引。虽然这不是您想要的,但对我来说似乎是最简单、最干净的解决方案。
初始请求 :GET /orders?count=30
返回:
{
"start"=1039;
"count"=30;
...//data
}
消费者由此计算出他想要请求:
下一个请求:
GET /orders?start=1009&count=30
然后返回:{
"start"=1009;
"count"=30;
...//data
}
除了原始索引,您还可以返回指向下一页的链接:
{
"next"="/orders?start=1009&count=30";
}
如果项目在中间插入或删除,这种方法就会中断。在这种情况下,您应该使用一些自动递增的持久值而不是索引。
关于scala - 当结果集可能发生变化时,如何使用 RESTful API 实现健壮的分页?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8487283/