高级用户搜索
直接使用 Management API 实现高级用户搜索条件。
执行搜索请求
使用 GET /api/users 进行用户搜索。请注意,这是一项需要认证的 Management API,和其他接口一样。交互方式详见 与 Management API 交互。
示例
请求
curl \
--location \
--request GET \
'http://<your-logto-endpoint>/api/users?search=%25alice%25'
响应
一个 User 实体数组。
[
{
"id": "MgUzzDsyX0iB",
"username": "alice_123",
"primaryEmail": "alice@some.email.domain",
"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:外部身份提供方颁发的用户标识符。
// 查找与钉钉社交身份关联的用户
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只匹配显式的 JSONnull,不会匹配缺失的键。- 嵌套对象递归匹配。
- 数组按元素匹配,不考虑顺序或重复。
同一个 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。