[ADP-311] 過濾
TIP
如果您不需要邏輯過濾,可以(MAY)使用簡單的 ?k=v&a=b。然而,如果您的用例涉及邏輯,請(RECOMMENDED)考慮實現這個方法,而不是發明一個新的機制。或者,如果您有更好的想法,可以向 API 設計原則所有者提出,因為並沒有真正通用的 '過濾' 標準。
概述
過濾是 RESTful API 中的一個常見功能,允許客戶端只檢索符合特定條件的數據。本指南概述了在 RESTful API 中實現過濾的標準化方法,重點關注嵌套屬性和其他常見方法。
指導
- 如果您的 API 支持過濾,應該(SHOULD)記錄過濾方法。
- 應該(SHOULD)使用通用查詢參數
filter
進行資源過濾。
我們提出兩種不同的過濾方法: RHS(右側)和 LHS(左側)。
RHS 適用於簡單查詢,而 LHS 適用於複雜的邏輯操作。
RHS 過濾
應該支持使用 RHS 查詢參數的複雜邏輯組合
httpGET /stores?filter=eq(name,John) HTTP/1.1
應該支持嵌套過濾
httpGET /stores?filter=eq(user(name),John) HTTP/1.1
可以支持邏輯操作
httpGET /stores?filter=gt(registeredAt,2024-07-13T00:00:00) HTTP/1.1
支持的操作:
eq
({屬性},{值}): 等於給定值ne
({屬性},{值}): 不等於給定值gt
({屬性},{值}): 大於給定值ge
({屬性},{值}): 大於或等於給定值lt
({屬性},{值}): 小於給定值le
({屬性},{值}): 小於或等於給定值in
({屬性},{值1},{值2},...): 包含列出的至少一個值like
({屬性},{值}): 包含類似於列出表達式的值exists
({屬性}): 給定路徑存在and
({查詢1},{查詢2},...): 邏輯與or
({查詢1},{查詢2},...): 邏輯或not
({查詢}): 邏輯非
LHS 過濾
應該支持使用通用
filter
查詢參數的簡單 LHS 過濾httpGET /users?filter.name=John HTTP/1.1
應該支持嵌套過濾
httpGET /users?filter.address.region=eu HTTP/1.1
應該支持使用
,
進行值的邏輯或操作httpGET /users?filter.role=MANAGER,SUPERVISOR
可以支持邏輯操作
httpGET /users?filter.createdAt:gt=2024-07-13T00:00:00 HTTP/1.1
支持的操作:
- filter.{屬性}
:eq
={值}: 等於(可以省略) - filter.{屬性}
:ne
={值}: 不等於 - filter.{屬性}
:gt
={值}: 大於 - filter.{屬性}
:ge
={值}: 大於或等於 - filter.{屬性}
:lt
={值}: 小於 - filter.{屬性}
:le
={值}: 小於或等於
- filter.{屬性}
可以支持逗號分隔的值進行邏輯或操作
httpGET /users?filter.name=John,Jason
可以添加額外的命名空間以滿足不同需求,圍繞屬性部分。如果實施,必須徹底記錄。
httpGET /licenses?filter=eq(features/featurelist,"nightwatch")
設計考慮
為什麼不使用僅屬性設計?
結果過濾的一種可能設計是僅使用屬性(property)名稱,例如:
http
GET /emaps?region=us&category=self-defined
這種方法的主要問題是可能與常見查詢參數發生衝突。隨著實現更多自定義查詢參數,發生衝突的可能性更大。
LHS/RHS
LHS(左側)意味著將邏輯放在 =
符號的左側。RHS 則放在右側。
左側括號
httpfilter[key1][gt]=x
右側括號
httpfilter[key1]=[gt]x
左側冒號
httpfilter.key:gte=y
右側冒號
httpfilter.key=gte:x
OpenAPI 示例
RHS 過濾示例
yaml
openapi: 3.1.0
info:
title: 商店 API
version: 1.0.0
paths:
/stores:
get:
summary: 獲取商店列表
parameters:
- in: query
name: filter
schema:
type: string
example: eq(name,John)
description: RHS 過濾參數
responses:
'200':
description: 成功回應
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/Store'
components:
schemas:
Store:
type: object
properties:
id:
type: integer
name:
type: string
registeredAt:
type: string
format: date-time
LHS 過濾示例
yaml
openapi: 3.1.0
info:
title: 用戶 API
version: 1.0.0
paths:
/users:
get:
summary: 獲取用戶列表
parameters:
- in: query
name: filter.name
schema:
type: string
example: John
description: 按名稱過濾
- in: query
name: filter.role
schema:
type: string
example: MANAGER,SUPERVISOR
description: 按角色過濾(支持多個值)
- in: query
name: filter.createdAt:gt
schema:
type: string
format: date-time
example: '2024-07-13T00:00:00'
description: 按創建時間過濾(大於)
responses:
'200':
description: 成功回應
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/User'
components:
schemas:
User:
type: object
properties:
id:
type: integer
name:
type: string
role:
type: string
createdAt:
type: string
format: date-time
參考
設計參考
- https://eclipse.dev/ditto/2.1/http-api-doc.html
- https://www.moesif.com/blog/technical/api-design/REST-API-Design-Filtering-Sorting-and-Pagination/
Changelog
2024.09.20
Add tips for common cases.