var assert = require('assert');

assert.deepEqual(qs.parse('price[gte]=10&price[lte]=100'), {
price: {
gte: 10,
lte: 100
}
});

缺點

冒號

與括號方法類似,您可以設計一個 API 將運算符置于 RHS(而不是 LHS)上。例如,將查找價格大于或等于 10,但小于或等于 100 的所有商品。 GET /items?price=gte:10&price=lte:100

好處

缺點

搜索查詢參數

如果您需要在端點上進行搜索,您可以直接使用搜索參數添加對過濾器和范圍的支持。如果您已經在使用 ElasticSearch 或其他基于 Lucene 的技術,您可以直接支持 Lucene 語法或 ElasticSearch 簡單查詢字符串。

例如,我們可以搜索包含術語 red chair 且價格大于或等于 10 且小于或等于 100 的商品: GET /items?q=title:red chair AND price:[10 TO 100]

此類 API 可以允許模糊匹配、增強某些術語等等。

好處

缺點

分頁

大多數返回實體列表的端點都需要某種分頁。

如果沒有分頁,簡單的搜索可能會返回數百萬甚至數十億的點擊量,從而導致額外的網絡流量。

分頁需要隱式排序。默認情況下,這可能是項目的唯一標識符,但也可以是其他有序字段,例如創建日期。

偏移分頁

這是最簡單的分頁形式。限制/偏移在使用 SQL 數據庫的應用程序中變得流行,這些數據庫已經將 LIMIT 和 OFFSET 作為 SQL SELECT 語法的一部分。實現限制/偏移分頁只需要很少的業務邏輯。

限制/偏移分頁看起來像。此查詢將返回從第 100 行開始的 20 行。 GET /items?limit=20&offset=100

例子

(假設查詢按創建日期降序排序)

  1. 客戶請求最近的項目: GET /items?limit=20
  2. 在滾動/下一頁上,客戶端發出第二個請求 GET /items?limit=20&offset=20
  3. 在滾動/下一頁上,客戶端發出第三個請求 GET /items?limit=20&offset=40

作為 SQL 語句,第三個請求如下所示:

SELECT
*
FROM
Items
ORDER BY Id
LIMIT 20
OFFSET 40;

好處

缺點

即使有限制,偏移分頁也很容易實現和理解,并且可以用于數據集上限較小的應用程序。

鍵集分頁

鍵集分頁使用最后一頁的過濾器值來獲取下一組項目。這些列將被索引。

例子

(假設查詢按創建日期降序排序)

  1. 客戶請求最近的項目: GET /items?limit=20
  2. 在滾動/下一頁上,客戶端從之前返回的結果中找到最小創建日期 2021-01-20T00:00:00。然后使用日期作為過濾器進行第二個查詢: GET /items?limit=20&created:lte:2021-01-20T00:00:00
  3. 在滾動/下一頁上,客戶端從之前返回的結果中找到最小創建日期 2021-01-19T00:00:00。然后使用日期作為過濾器進行第三次查詢: GET /items?limit=20&created:lte:2021-01-19T00:00:00
SELECT
*
FROM
Items
WHERE
created <= '2021-01-20T00:00:00'
ORDER BY Id
LIMIT 20

好處

缺點

鍵集分頁對于具有單個自然高基數鍵的數據非常有效,例如可以使用時間戳的時間序列或日志數據。

查找分頁

查找分頁是鍵集分頁的擴展。通過添加 after_id 或 start_id URL 參數,我們可以消除分頁與過濾器和排序的緊密耦合。由于唯一標識符本質上是高基數,因此我們不會遇到與按低基數字段(如狀態枚舉或類別名稱)排序不同的問題。

基于搜索的分頁的問題是當需要自定義排序順序時很難實現。

例子

(假設查詢按創建日期升序排序)

  1. 客戶請求最近的項目: GET /items?limit=20
  2. 在滾動/下一頁上,客戶端從之前返回的結果中找到最后一個 id“20”。然后使用它作為起始 id 進行第二次查詢: GET /items?limit=20&after_id=20
  3. 在滾動/下一頁上,客戶端從之前返回的結果中找到最后一個 id“40”。然后使用它作為起始 id 進行第三次查詢: GET /items?limit=20&after_id=40

尋求分頁可以被提煉成一個子句 where

SELECT
*
FROM
Items
WHERE
Id > 20
LIMIT 20

如果按 id 排序,上面的示例可以正常工作,但如果我們想按電子郵件字段排序怎么辦?對于每個請求,后端需要首先獲取標識符與 after_id 匹配的項目的電子郵件值。然后,使用該值作為過濾器執行第二個查詢。 where

讓我們考慮一下查詢,后端將需要兩個查詢。第一個查詢可能是使用哈希表進行 O(1) 查找,以獲得電子郵件數據透視值。將此輸入到第二個查詢中,以僅檢索電子郵件位于 after_email 之后的項目。我們按電子郵件和 ID 兩列進行排序,以確保在兩封電子郵件相同的情況下有穩定的排序。這對于較低基數字段至關重要。 GET /items?limit=20&after_id=20&sort_by=email

1.

SELECT
email AS AFTER_EMAIL
FROM
Items
WHERE
Id = 20

2.

SELECT
*
FROM
Items
WHERE
Email >= [AFTER_EMAIL]
ORDER BY Email, Id
LIMIT 20

好處

缺點

Seek 分頁是一個很好的整體分頁策略,也是我們在 Moesif Public API 上實現的。它需要在后端進行更多的工作,但確保不會給 API 的客戶端/用戶增加額外的復雜性,同時即使在更大的搜索范圍內也能保持性能。

排序

與過濾一樣,排序對于任何返回大量數據的 API 端點來說都是一項重要功能。如果您要返回用戶列表,您的 API 用戶可能希望按上次修改日期或電子郵件進行排序。

為了啟用排序,許多 API 添加了 sort 或 sort_by URL 參數,該參數可以將字段名稱作為值。

然而,良好的 API 設計可以靈活地指定升序或降序。與過濾器一樣,指定順序需要將三個組件編碼為鍵/值對。

格式示例

多列排序

不建議使用排序和順序不配對的最后一種設計。您最終可能允許按兩列或更多列排序:

SELECT
email
FROM
Items
ORDER BY Last_Modified DESC, Email ASC
LIMIT 20

要編碼此多列排序,您可以允許多個字段名稱,例如

  GET /users?sort_by=desc(last_modified),asc(email) 或

GET /users?sort_by=-last_modified,+email

如果排序字段和排序不配對,則需要保留 URL 參數排序;否則,什么排序應該與什么字段名稱配對是不明確的。然而,許多服務器端框架在反序列化到映射后可能不會保留順序。

您還必須確保任何緩存鍵都考慮 URL 參數排序,但這會給緩存大小帶來壓力。

結論

良好的 API 設計是開發者體驗 (DX) 的關鍵組成部分。 API 規范可以比許多底層服務器實現更持久,這需要考慮 API 的未來用例。

原文鏈接:REST API Design: Filtering, Sorting, and Pagination

上一篇:

基本 API 設計模式:打造卓越 Web 服務的指南

下一篇:

使用 RESTful API 探索藝術世界
#你可能也喜歡這些API文章!

我們有何不同?

API服務商零注冊

多API并行試用

數據驅動選型,提升決策效率

查看全部API→
??

熱門場景實測,選對API

#AI文本生成大模型API

對比大模型API的內容創意新穎性、情感共鳴力、商業轉化潛力

25個渠道
一鍵對比試用API 限時免費

#AI深度推理大模型API

對比大模型API的邏輯推理準確性、分析深度、可視化建議合理性

10個渠道
一鍵對比試用API 限時免費