Skip to main content

Advanced user search

Directly using Management API to leverage advanced user search conditions.

Perform a search request​

Use GET /api/users for searching users. Note it is a Management API that requires auth like others. See Interact with Management API for the interaction recipe.

Sample​

Request

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

Response

An array of User entity.

[
{
"id": "MgUzzDsyX0iB",
"username": "alice_123",
"primaryEmail": "alice@some.email.domain",
"primaryPhone": null,
"name": null,
"avatar": null
// ...
}
]

Parameters​

A search request consists of the following parameter keys:

  • Search keywords: search, search.*
  • Search mode for fields: mode, mode.* (default value 'like', available ['exact', 'like', 'similar_to', 'posix'])
  • Joint mode: joint or jointMode (default value 'or', available ['or', 'and'])
  • Is case-sensitive: isCaseSensitive (default value false)

This API has pagination enabled.

Let's go through them via some examples. All search params will be formatted as a constructor of URLSearchParams.

warning:

Search mode is set to like by default, which uses Approximate string matching ("fuzzy search").

note:

All fuzzy search modes only support matching one value per field. If you need to match multiple values for a single field, you should use the "exact" mode. See Exact match and case sensitivity for details.

If you want to perform a fuzzy search over all available fields, just provide a value for key search. It will use the like operator under the hood:

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

This search will iterate over all available fields in a user search, i.e. id, primaryEmail, primaryPhone, username, name.

Specify fields​

What if you want to limit the search in name only? To search someone that includes foo in their name, just use the . symbol to specify the field:

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

Remember nested fields are not supported, e.g. search.name.first will result an error.

You can also specify multiple fields at the same time:

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

Means to search users that have foo in name OR their email ends with @gmail.com.

Changing the joint mode​

If you want the API only returns the result that satisfies ALL the conditions, set the joint mode to and:

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

Means to search users that have foo in name AND their email ends with @gmail.com.

Exact match and case sensitivity​

Say you want to search whose name is exact "Alice". You can set mode.name to use exact match.

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

You may find it has the same effect when using the like mode (default) v.s. specifying exact. One difference is exact mode uses = for comparing while like uses like or ilike. Theoretically = should have a better performance.

Plus, in exact mode, you can pass multiple values for matching, and they will be connected with or:

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

It will match the users with name "Alice" OR "Bob".

By default search is case-insensitive. To be more precise, set the search as case-sensitive:

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

Note isCaseSensitive is a global config. Thus EVERY field will follow it.

Regular expression (RegEx)​

PostgreSQL supports two types of regular expressions, similar to and posix. Set mode to similar_to or posix to search by regular expressions:

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

Note Mode similar_to only works in case-sensitive searches.

Match mode override​

By default, all keywords will inherit the match mode from the general search:

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

To override for specific field:

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