API分页最佳实践
我喜欢一些帮助处理一个奇怪的边缘情况与我正在建设的分页API。
像许多API一样,这个分页结果很大。 如果你查询/ foos,你会得到100个结果(即foo#1-100)和一个到/ foos?page = 2的链接,它应该返回foo#101-200。
不幸的是,如果在API消费者进行下一个查询之前从数据集中删除foo#10,那么/ foos?page = 2将偏移100并返回foos#102-201。
对于试图拉动所有foos的API消费者来说,这是一个问题 - 他们不会收到foo#101。
处理这个问题的最佳做法是什么? 我们希望尽可能轻量化(即避免处理API请求的会话)。 来自其他API的示例将不胜感激!
我不完全确定你的数据是如何处理的,所以这可能会或可能不会起作用,但是你是否考虑过使用时间戳字段进行分页?
当你查询/ foos时,你会得到100个结果。 然后你的API应该返回类似的东西(假设JSON,但是如果它需要XML,可以遵循相同的原则):
{
"data" : [
{ data item 1 with all relevant fields },
{ data item 2 },
...
{ data item 100 }
],
"paging": {
"previous": "http://api.example.com/foo?since=TIMESTAMP1"
"next": "http://api.example.com/foo?since=TIMESTAMP2"
}
}
请注意,只有使用一个时间戳会依赖于结果中的隐式“限制”。 您可能需要添加明确的限制,或者使用until
属性。
时间戳可以使用列表中的最后一个数据项来动态确定。 这似乎或多或少是Facebook如何在Graph API中进行分页(向下滚动到底部以按照上面给出的格式查看分页链接)。
一个问题可能是如果你添加一个数据项,但是根据你的描述,它听起来像将被添加到最后(如果没有,让我知道,我会看看如果我可以改善这一点)。
你有几个问题。
首先,你有你引用的例子。
如果插入行,您也会遇到类似的问题,但在这种情况下,用户会得到重复的数据(可以说比丢失数据更容易管理,但仍然是一个问题)。
如果你没有对原始数据集进行快照,那么这只是一个事实。
你可以让用户做一个明确的快照:
POST /createquery
filter.firstName=Bob&filter.lastName=Eubanks
结果如下:
HTTP/1.1 301 Here's your query
Location: http://www.example.org/query/12345
然后你可以整天翻页,因为它现在是静态的。 这可以是相当轻的重量,因为您可以捕获实际的文档键而不是整行。
如果用例仅仅是您的用户需要(并且需要)所有数据,那么您可以简单地将其提供给他们:
GET /query/12345?all=true
并发送整个套件。
如果你已经分页,你也可以通过一些关键字对数据进行排序。 为什么不让API客户端在URL中包含先前返回的集合的最后一个元素的关键字,并向SQL查询中添加WHERE
子句(或者如果您不使用SQL,则是等价的),以便它仅返回那些用于哪个键大于这个值?