> ## Documentation Index
> Fetch the complete documentation index at: https://learn.social.plus/llms.txt
> Use this file to discover all available pages before exploring further.

# Search and Query Users

> Search for users by display name and query paginated user collections in social.plus SDK.

Use the user repository when your app needs to find people by display name or browse a paginated user list. Search is for keyword-driven flows such as member pickers, while query is for directory-style lists where sorting and pagination matter more than a search keyword.

<Info>
  Deleted users are automatically excluded from search and query results.
</Info>

## Parameters

This page covers two user-list operations. Choose the operation first, then use the inputs table in each section for the exact SDK call shape.

| Operation                    | Use when                                                 | Required inputs                                                       | Platforms                         |
| ---------------------------- | -------------------------------------------------------- | --------------------------------------------------------------------- | --------------------------------- |
| Search users by display name | You have a display-name keyword and want matching users. | Display-name keyword, callback or collection observer where required. | TypeScript, iOS, Android, Flutter |
| Query users                  | You need a paginated user list without a search keyword. | Callback or sort option where required.                               | TypeScript, iOS, Android, Flutter |

## Search users by display name

Use search when the user types a display-name keyword. Search keywords must be at least 3 characters long. When a keyword is provided, the server ranks matching results by search relevance; supported sort options can then control the returned order.

### Inputs

| Platform   | Method                                                                 | Required inputs         | Optional inputs                                      | Result shape                                                         |
| ---------- | ---------------------------------------------------------------------- | ----------------------- | ---------------------------------------------------- | -------------------------------------------------------------------- |
| TypeScript | `UserRepository.searchUserByDisplayName(params, callback)`             | `displayName`, callback | `limit`, `matchType`, `searchBy`                     | Starts a live collection observer and returns an unsubscriber.       |
| iOS        | `userRepository.searchUsers(displayName, sortBy:, matchType:)`         | `displayName`, `sortBy` | `matchType`                                          | Returns a live collection observed with an `AmityNotificationToken`. |
| Android    | `userRepository.searchUsers(keyword).build().query()`                  | `keyword`               | `sortBy(...)`, `matchType(...)`                      | Returns `Flowable<PagingData<AmityUser>>`.                           |
| Flutter    | `AmityCoreClient.newUserRepository().searchUserByDisplayName(keyword)` | `keyword`               | `sortBy(...)`, `matchType(...)`, paging token, limit | Returns paging data through the query builder.                       |

<Note>
  TypeScript search parameters intentionally do not include `sortBy`; use `getUsers(...)` when you need TypeScript user-list sorting.
</Note>

### Special character handling

<Info>
  With display-name sorting, users are sorted alphabetically by their display names using ICU collation for the English locale. This means that special characters such as Ä are treated as variants of A. For example, a sorted list might appear as: **adam, Älex, Alice, Arthur, charlie, Kristen**.

  When providing a search keyword, the API performs an exact-match lookup for special characters:

  * Searching for "Äli" only returns users whose display name contains "Äli", such as "Älise".
  * Searching for "Alice" does not return "Älice".
</Info>

Use the platform search method to retrieve users whose display name matches the search keyword.

<CodeGroup>
  ```typescript TypeScript theme={null}
  import { UserRepository } from '@amityco/ts-sdk';

  let loadMoreUsers: (() => void) | undefined;

  const unsubscribe = UserRepository.searchUserByDisplayName(
    { displayName: 'Joe', limit: 20 },
    ({ data: users, loading, error, hasNextPage, onNextPage }) => {
      if (loading) return;

      if (error) {
        console.error('Failed to search users', error);
        return;
      }

      console.log(`Found ${users.length} users`);
      console.log(`More pages available: ${hasNextPage}`);
      loadMoreUsers = onNextPage;
    },
  );

  // Call loadMoreUsers?.() from your load-more action.
  // Call unsubscribe() when the screen no longer needs search updates.
  ```

  ```swift iOS theme={null}
  var token: AmityNotificationToken?

  func searchUserExample() {
      let liveCollection = userRepository.searchUsers(
          "<display-name>",
          sortBy: .displayName,
          matchType: .default
      )
      token = liveCollection.observe { collection, error in
          let users = collection.snapshots
          print("Found \(users.count) users")
      }
  }
  ```

  ```kotlin Android theme={null}
  fun searchUsers(userRepository: AmityUserRepository) {
      userRepository.searchUsers("Brian")
          .sortBy(sortOption = AmityUserSortOption.DISPLAYNAME) // optional
          .build()
          .query()
          .doOnNext { users: PagingData<AmityUser> ->
              // PagingData<AmityUser>
          }
          .doOnError { error ->
              Log.e("UserRepo", "Failed to search users", error)
          }
          .subscribe()
  }
  ```

  ```dart Flutter theme={null}
  final _amityUsers = <AmityUser>[];
  late PagingController<AmityUser> _amityUsersController;

  void searchUserByDisplayName(String keyword) {
    _amityUsersController = PagingController(
      pageFuture: (token) => AmityCoreClient.newUserRepository()
          .searchUserByDisplayName(keyword)
          .sortBy(AmityUserSortOption.DISPLAY)
          .matchType(AmityUserSearchMatchType.DEFAULT)
          .getPagingData(token: token, limit: 20),
      pageSize: 20,
    )..addListener(
        () {
          if (_amityUsersController.error == null) {
            _amityUsers.clear();
            _amityUsers.addAll(_amityUsersController.loadedItems);
          }
        },
      );
  }
  ```
</CodeGroup>

## Query users

Use `getUsers()` when you need a paginated user list without a display-name keyword. TypeScript query sorting supports `firstCreated` and `lastCreated`; iOS, Android, and Flutter also expose display-name sorting.

### Inputs

| Platform   | Method                                           | Required inputs | Optional inputs                          | Result shape                                                         |
| ---------- | ------------------------------------------------ | --------------- | ---------------------------------------- | -------------------------------------------------------------------- |
| TypeScript | `UserRepository.getUsers(params, callback)`      | callback        | `sortBy`, `limit`, `filter`, `matchType` | Starts a live collection observer and returns an unsubscriber.       |
| iOS        | `userRepository.getUsers(sortBy)`                | `sortBy`        | None in this call shape                  | Returns a live collection observed with an `AmityNotificationToken`. |
| Android    | `userRepository.getUsers().build().query()`      | None            | `sortBy(...)`                            | Returns `Flowable<PagingData<AmityUser>>`.                           |
| Flutter    | `AmityCoreClient.newUserRepository().getUsers()` | None            | `sortBy(...)`, paging token, limit       | Returns paging data through the query builder.                       |

<Info>
  Deleted users are excluded from query results.
</Info>

Use the platform query method when you need a paginated user list rather than keyword search.

<CodeGroup>
  ```typescript TypeScript theme={null}
  import { UserRepository } from '@amityco/ts-sdk';

  let loadMoreUsers: (() => void) | undefined;

  const unsubscribe = UserRepository.getUsers(
    { sortBy: 'lastCreated', limit: 20 },
    ({ data: users, loading, error, hasNextPage, onNextPage }) => {
      if (loading) return;

      if (error) {
        console.error('Failed to query users', error);
        return;
      }

      console.log(`Loaded ${users.length} users`);
      console.log(`More pages available: ${hasNextPage}`);
      loadMoreUsers = onNextPage;
    },
  );

  // Call loadMoreUsers?.() from your load-more action.
  // Call unsubscribe() when the screen no longer needs user list updates.
  ```

  ```swift iOS theme={null}
  var token: AmityNotificationToken?

  func queryUsersExample() {
      let liveCollection = userRepository.getUsers(.displayName)
      token = liveCollection.observe { collection, error in
          let users = collection.snapshots
          print("Loaded \(users.count) users")
      }
  }
  ```

  ```kotlin Android theme={null}
  fun queryUsers(userRepository: AmityUserRepository) {
      userRepository.getUsers()
          .sortBy(sortOption = AmityUserSortOption.DISPLAYNAME) // optional
          .build()
          .query()
          .doOnNext { users: PagingData<AmityUser> ->
              // PagingData<AmityUser>
          }
          .doOnError { error ->
              Log.e("UserRepo", "Failed to query users", error)
          }
          .subscribe()
  }
  ```

  ```dart Flutter theme={null}
  final _amityUsers = <AmityUser>[];
  late PagingController<AmityUser> _amityUsersController;

  void getUsers(AmityUserSortOption sortOption) {
    _amityUsersController = PagingController(
      pageFuture: (token) => AmityCoreClient.newUserRepository()
          .getUsers()
          .sortBy(sortOption)
          .getPagingData(token: token, limit: 20),
      pageSize: 20,
    )..addListener(
        () {
          if (_amityUsersController.error == null) {
            _amityUsers.clear();
            _amityUsers.addAll(_amityUsersController.loadedItems);
          }
        },
      );
  }
  ```
</CodeGroup>

## Platform notes

* TypeScript `searchUserByDisplayName(...)` starts a live collection observer, but its search params do not expose `sortBy`.
* iOS search and query methods require an `AmityUserSortOption`.
* Android and Flutter default user search/query sorting to display name when no explicit sort is provided.
* Use pagination controls from the callback, live collection, `PagingData`, or Flutter `PagingController` instead of loading all users at once.

## Related topics

<CardGroup cols={2}>
  <Card title="Get User Information" href="./get-user-information" icon="user">
    Retrieve one user, batch lookup users where supported, or query user collections.
  </Card>

  <Card title="Update User Information" href="./update-user-information" icon="pencil">
    Modify user profile fields.
  </Card>
</CardGroup>
