我正在实现一个RESTful API,它将Orders作为资源公开,并通过结果集支持分页:
GET /orders?start=1&end=30
其中分页的订单按ordered_at
时间戳排序,降序。这基本上是SO问题Pagination in a REST web application中的#1方法。
如果用户请求订单的第二页(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中。
答案 0 :(得分:5)
我这样做的方法是将索引从旧到新。所以他们永远不会改变然后在没有任何启动参数的情况下查询时,返回最新页面。此外,响应应包含指示包含哪些元素的索引,因此您可以计算下一个较旧页面所需的索引。虽然这不是你想要的,但对我来说似乎是最简单,最干净的解决方案。
初始请求: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";
}
如果在中间插入或删除项目,则此方法会中断。在这种情况下,您应该使用一些自动递增持久值而不是索引。
答案 1 :(得分:1)
可悲的事实是,我看到的所有网站都在这个意义上“破碎”,所以一定不可能有一个简单的方法来实现这一目标。
快速解决方法可能会颠倒顺序,因此项目的位置是绝对的,并且与新添加的内容保持不变。在您的首页,您可以提供最新的索引,以确保从那里开始一致的导航。
答案 2 :(得分:1)
使用RESTFUL API,应用程序状态应该在客户端中。在这里,应用程序状态应该是某种时间戳或版本号,告诉您何时开始查看数据。在服务器端,您将需要某种形式的审计跟踪,这是正确的服务器数据,因为它不依赖于是否有客户端以及他们做了什么。至少,它应该知道数据上次更改的时间。这里与REST没有矛盾。
您可以在get中添加版本参数。当客户端首先需要页面时,通常不会发送版本。服务器回复包含一个。例如,如果对下一页/其他页面的回复中有链接,则这些链接包含& version = ...客户端应在需要另一页时发送该版本。
当服务器收到某个版本的请求时,它至少应该知道自客户端开始查看以来数据是否已更改,并且取决于您拥有哪种审计跟踪,以及它们的更改方式。如果没有,它会正常回答,传输相同的版本号。如果有,它至少可以告诉客户。根据它对数据如何变化的了解程度,它可能会相应地回复数据。
举个例子,假设您收到了一个包含start,end,version的请求,并且您知道由于版本是最新的,因此删除了3行。您可以使用start-3,end-3,new version发送重定向。
答案 3 :(得分:1)
WebSockets可以做到这一点。您可以使用pusher.com之类的内容来捕获对数据库的实时更改,并将更改传递给客户端。然后,您可以绑定不同的推送事件以使用模型和集合。
答案 4 :(得分:0)
只是把它扔出去。请随时告诉我它是否完全错误,为什么会这样。
此方法尝试使用 left_off 变量进行排序,而不使用偏移量。
考虑您需要按时间戳order_at DESC进行排序。 所以当我要求第一个结果集时 它是
SELECT * FROM Orders ORDER BY order_at DESC LIMIT 25;
正确? 当你要求第一页时就是这种情况(就URL而言,可能是没有任何
的请求) ?yoursomething.com/orders的限制= 25安培; left_off = $时间戳强>
然后收到您的数据集。只需获取上次查看项目的时间戳即可。 2015-12-21 13:00:49
现在请求接下来的25个项目转到: yoursomething.com/orders?limit=25&left_off=2015-12-21 13:00:49 (最后查看时间戳)
在Sql中,您只需进行相同的查询,并说出时间戳等于或小于$ left_off的位置
SELECT * FROM (SELECT * FROM Orders ORDER BY order_at DESC) as a
WHERE a.order_at < '2015-12-21 13:00:49' LIMIT 25;
您应该从上次看到的项目中获得下一个25项。
对于那些看到这个答案的人。如果这种方法是相关的,甚至可能是首选,请评论。谢谢。