跳至主要內容

進階使用者搜尋

直接使用 Management API 以進行進階使用者搜尋條件。

執行搜尋請求​

使用 GET /api/users 來搜尋使用者。請注意,這是一個需要驗證 (Authentication) 的 Management API,與其他 API 相同。互動方式請參考 與 Management API 互動。

範例​

請求

curl \
--location \
--request GET \
'http://<your-logto-endpoint>/api/users?search=%25alice%25'

回應

一個 User 實體的陣列。

[
{
"id": "MgUzzDsyX0iB",
"username": "alice_123",
"primaryEmail": "[email protected]",
"primaryPhone": null,
"name": null,
"avatar": null
// ...
}
]

參數​

搜尋請求包含以下參數鍵:

  • 搜尋關鍵字:search、search.*
  • 欄位搜尋模式:mode、mode.*(預設值 'like',可用值 ['exact', 'like', 'similar_to', 'posix'])
  • 聯集模式:joint 或 jointMode(預設值 'or',可用值 ['or', 'and'])
  • 是否區分大小寫:isCaseSensitive(預設值 false)

此 API 支援 分頁。

以下將透過範例逐一說明。所有搜尋參數將以 URLSearchParams 建構式格式呈現。

注意:

搜尋模式預設為 like,即使用 近似字串比對(「模糊搜尋」)。

備註:

所有模糊搜尋模式僅支援每個欄位比對一個值。若需比對單一欄位多個值,請使用 "exact" 模式。詳見 精確比對與區分大小寫。

若要對所有可用欄位進行模糊搜尋,只需為 search 鍵提供值。底層將使用 the like operator:

new URLSearchParams([['search', '%foo%']]);

此搜尋會遍歷使用者搜尋中的所有可用欄位,即 id、primaryEmail、primaryPhone、username、name。

指定欄位​

若只想限定在 name 欄位搜尋,搜尋名稱中包含 foo 的人,只需用 . 符號指定欄位:

new URLSearchParams([['search.name', '%foo%']]);

請注意,不支援巢狀欄位,例如 search.name.first 會導致錯誤。

你也可以同時指定多個欄位:

new URLSearchParams([
['search.name', '%foo%'],
['search.primaryEmail', '%@gmail.com'],
]);

代表搜尋名稱含有 foo 或 電子郵件結尾為 @gmail.com 的使用者。

更改聯集模式​

若希望 API 僅回傳同時滿足所有條件的結果,請將聯集模式設為 and:

new URLSearchParams([
['search.name', '%foo%'],
['search.primaryEmail', '%@gmail.com'],
['joint', 'and'],
]);

代表搜尋名稱含有 foo 且 電子郵件結尾為 @gmail.com 的使用者。

精確比對與區分大小寫​

假設你想搜尋名稱完全等於 "Alice" 的使用者,可以將 mode.name 設為精確比對。

new URLSearchParams([
['search.name', 'Alice'],
['mode.name', 'exact'],
]);

你可能會發現預設的 like 模式與指定 exact 效果相同。不同之處在於 exact 模式使用 = 比對,而 like 則用 like 或 ilike。理論上 = 效能更佳。

此外,在 exact 模式下,你可以傳遞多個值進行比對,這些值會以 or 連接:

new URLSearchParams([
['search.name', 'Alice'],
['search.name', 'Bob'],
['mode.name', 'exact'],
]);

將會比對名稱為 "Alice" 或 "Bob" 的使用者。

預設搜尋不區分大小寫。若需精確比對,可將搜尋設為區分大小寫:

new URLSearchParams([
['search.name', 'Alice'],
['search.name', 'Bob'],
['mode.name', 'exact'],
['isCaseSensitive', 'true'],
]);

請注意,isCaseSensitive 為全域設定,因此所有欄位都會遵循此設定。

正規表示式(RegEx)​

PostgreSQL 支援兩種正規表示式,similar to 與 posix。將 mode 設為 similar_to 或 posix 以正規表示式搜尋:

new URLSearchParams([
['search', '^T.?m Scot+$'],
['mode', 'posix'],
]);

注意 similar_to 模式僅適用於區分大小寫的搜尋。

比對模式覆寫​

預設情況下,所有關鍵字會繼承一般搜尋的比對模式:

new URLSearchParams([
['search', '^T.?m Scot+$'],
['mode', 'posix'],
['search.primaryEmail', 'tom%'], // Posix 模式
['joint', 'and'],
]);

若要針對特定欄位覆寫:

new URLSearchParams([
['search', '^T.?m Scot+$'],
['mode', 'posix'],
['search.primaryEmail', 'tom%'], // Like 模式
['mode.primaryEmail', 'like'],
['search.phone', '0{3,}'], // Posix 模式
['joint', 'and'],
]);

依外部身分查找​

若要查找與社交或企業級單一登入 (SSO) 身分綁定的使用者,請同時傳遞以下三個查詢參數以進行精確查找:

  • identityType:social 代表社交連接器身分,sso 代表企業級單一登入 (SSO) 身分。
  • identityProvider:社交身分的連接器目標(例如 dingtalk),或企業級單一登入 (SSO) 身分的簽發者 (Issuer)。
  • identityId:外部身分提供者簽發的使用者識別碼。
// 查找與 DingTalk 社交身分綁定的使用者
new URLSearchParams([
['identityType', 'social'],
['identityProvider', 'dingtalk'],
['identityId', 'dingtalk-open-id'],
]);
// 查找與企業級單一登入 (SSO) 身分綁定的使用者
new URLSearchParams([
['identityType', 'sso'],
['identityProvider', 'https://example.com/issuer'],
['identityId', 'enterprise-user-id'],
]);

身分篩選會與其他搜尋條件以 AND 邏輯結合。例如,進一步以關鍵字縮小身分查找範圍:

new URLSearchParams([
['identityType', 'social'],
['identityProvider', 'dingtalk'],
['identityId', 'dingtalk-open-id'],
['search', '%foo%'],
]);

依自訂資料查找​

若要根據 自訂資料 中儲存的精確值查找使用者,請在 GET /api/users 請求中傳遞一個或多個 customData 查詢參數。每個值必須是 URL 編碼的 JSON 物件:

curl \
--get \
--data-urlencode 'customData={"qq":114514}' \
'http://<your-logto-endpoint>/api/users'

--data-urlencode 會自動為你編碼 JSON 物件。等效的請求 URL 為 GET /api/users?customData=%7B%22qq%22%3A114514%7D。

備註:

當租戶擁有大量使用者時,自訂資料查找可能較慢。建議搭配 customData 與其他篩選條件(如 search 或身分查找)縮小查詢範圍。

Logto 會使用 JSONB 包含 比對使用者的 custom_data。只需比對值中包含的鍵,使用者自訂資料中的其他鍵會被忽略。

  • 型別嚴格:數字 114514 不會比對字串 "114514"。
  • 字串比對區分大小寫。
  • null 僅比對明確的 JSON null,不會比對缺少的鍵。
  • 巢狀物件會遞迴比對。
  • 陣列會以元素比對,不考慮順序或重複。

單一 JSON 物件內所有鍵必須同時比對(AND)。若傳遞多個 customData,只要任一物件比對即符合(OR):

curl \
--get \
--data-urlencode 'customData={"qq":114514}' \
--data-urlencode 'customData={"wechat":"logto"}' \
'http://<your-logto-endpoint>/api/users'

自訂資料篩選永遠與其他篩選條件(如 search、身分查找(identityType、identityProvider、identityId)、excludeRoleId、excludeOrganizationId)以 AND 結合。例如,以下請求會回傳 qq 為 114514 且使用者名稱包含 alice 的使用者:

curl \
--get \
--data-urlencode 'customData={"qq":114514}' \
--data-urlencode 'search.username=%alice%' \
'http://<your-logto-endpoint>/api/users'

mode、joint 與 isCaseSensitive 參數僅影響關鍵字搜尋,對 customData 無效。

若 customData 值不是有效的 JSON 物件(如 [] 或 114514)、為空物件 {}、或在任一層級包含空物件或空陣列(如 {"profile":{}} 或 {"tags":[]}),API 會回傳 400 Bad Request。巢狀參數名稱如 customData.qq、customData[qq]、mode.customData 也會被 400 拒絕。