我喜欢一些一些帮助处理一个奇怪的边缘情况与分页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的示例将非常感谢!
参考API分页设计,我们可以通过游标来设计分页API
他们有一个概念,叫做游标,它是指向一行的指针。你可以对数据库说"在那之后返回100行"对于数据库来说,这要容易得多,因为很有可能通过带索引的字段来标识行。这样你就不需要获取和跳过这些行了,你可以直接跳过它们。
一个例子:
GET /api/products
{"items": [...100 products],
"cursor": "qWe"}
API返回一个(不透明的)字符串,你可以使用它来检索下一页:
GET /api/products?cursor=qWe
{"items": [...100 products],
"cursor": "qWr"}
实现方面有许多选项。通常,您有一些排序标准,例如,产品id。在这种情况下,您将使用一些可逆算法(比如哈希)对产品id进行编码。在接收到带有游标的请求时,对其进行解码并生成类似WHERE id >:cursor LIMIT 100的查询。
优势:
通过游标可以提高数据库的查询性能
处理好时,新内容插入到db查询
劣势:
使用无状态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
把全套装备都寄过来。