val channelClient = client.channel("messaging", "general")
val offset = 0
val limit = 10
val sort = QuerySortByField<Member>()
// Query members by user name
val filterByName = Filters.eq("name", "tommaso")
channelClient.queryMembers(offset, limit, filterByName, sort).enqueue { result ->
when (result) {
is Result.Success -> {
val members: List<Member> = result.value
}
is Result.Failure -> {
Log.e(TAG, String.format("There was an error %s", result.value), result.value.extractCause())
}
}
}
// Autocomplete members by user name (names containing "tom")
val filterByAutoComplete = Filters.autocomplete("name", "tom")
// Query all members
val filterAll = Filters.neutral()Querying Members
The queryMembers method allows you to list and paginate members for a channel. It supports filtering on numerous criteria to efficiently return member information. This is useful for channels with large member lists where you need to search for specific members or display the complete member roster.
// Query members by user name
channel.queryMembers({ name: "tommaso" });
// Autocomplete members by user name
channel.queryMembers({ name: { $autocomplete: "tom" } });
// Query all members
channel.queryMembers({});// Query by user name
let controller = chatClient.memberListController(
query: .init(cid: .init(type: .messaging, id: "general"), filter: .equal(.name, to: "tommaso"))
)
controller.synchronize { error in
print(error ?? controller.members)
}
// Autocomplete members by user name
let autocompleteController = chatClient.memberListController(
query: .init(cid: .init(type: .messaging, id: "general"), filter: .autocomplete(.name, text: "tom"))
)
// Query all members
let allMembersController = chatClient.memberListController(
query: .init(cid: .init(type: .messaging, id: "general"), filter: .none)
)# Query members by user name
response = channel.query_members(
filter_conditions={"name": "tommaso"},
sort=[{"field": "created_at", "direction": 1}],
)
# Autocomplete members by user name
response = channel.query_members(filter_conditions={"name": {"$autocomplete": "tom"}})
# Query all members
response = channel.query_members(filter_conditions={})// Query members by user name
channel.queryMembers(
filter: Filter.equal('name', 'tommaso'),
);
// Autocomplete members by user name
channel.queryMembers(
filter: Filter.autocomplete('name', 'tom'),
);
// Query all members
channel.queryMembers();// Query members by user name
Channel->QueryMembers(FFilter::Equal(TEXT("name"), TEXT("tommaso")));
// Autocomplete members by user name
Channel->QueryMembers(FFilter::Autocomplete(TEXT("name"), TEXT("tom")));
// Query all members
Channel->QueryMembers();# Query members by user name
response = channel.query_members(
filter_conditions: { "name" => "tommaso" },
sort: [{ "field" => "created_at", "direction" => 1 }]
)
# Autocomplete members by user name
response = channel.query_members(filter_conditions: { "name" => { "$autocomplete" => "tom" } })
# Query all members
response = channel.query_members(filter_conditions: {})// Query members by user name
await channelClient.QueryMembersAsync(new QueryMembersRequest
{
FilterConditions = new Dictionary<string, object> { { "name", "tommaso" } },
});
// Autocomplete members by user name
await channelClient.QueryMembersAsync(new QueryMembersRequest
{
FilterConditions = new Dictionary<string, object>
{
{ "name", new Dictionary<string, string> { { "$autocomplete", "tom" } } },
},
});
// Query all members
await channelClient.QueryMembersAsync(new QueryMembersRequest
{
FilterConditions = new Dictionary<string, object>(),
});// Query members by user name
$channel->queryMembers(
["name" => "tommaso"],
[["created_at" => 1]],
["limit" => 10, "offset" => 0]
);
// Autocomplete members by user name
$channel->queryMembers(["name" => ["$autocomplete" => "tom"]]);
// Query all members
$channel->queryMembers([]);// Query members by user name
ch.QueryMembers(ctx, &QueryOption{
Filter: map[string]interface{}{
"name": "tommaso",
},
Offset: 0,
Limit: 10,
},
&SortOption{Field: "created_at", Direction: 1},
)
// Autocomplete members by user name
ch.QueryMembers(ctx, &QueryOption{
Filter: map[string]interface{}{
"name": map[string]interface{}{"$autocomplete": "tom"},
},
})
// Query all members
ch.QueryMembers(ctx, &QueryOption{
Filter: make(map[string]interface{}),
})// Android SDK
ChannelClient channelClient = client.channel("messaging", "general");
int offset = 0;
int limit = 10;
QuerySortByField<Member> sort = new QuerySortByField<>();
// Query members by user name
FilterObject filterByName = Filters.eq("name", "tommaso");
channelClient.queryMembers(offset, limit, filterByName, sort, emptyList()).enqueue(result -> {
if (result.isSuccess()) {
List<Member> members = result.data();
} else {
// Handle result.error()
}
});
// Autocomplete members by user name
FilterObject filterByAutoComplete = Filters.autocomplete("name", "tom");
// Query all members
FilterObject filterAll = NeutralFilterObject.INSTANCE;var channel = await Client.GetOrCreateChannelWithIdAsync(ChannelType.Messaging, channelId: "my-channel-id");
// Query members by ID
var filters = new Dictionary<string, object>
{
{
"id", new Dictionary<string, object>
{
{ "$in", new[] { "user-id-1", "user-id-2" } }
}
}
};
var membersResult = await channel.QueryMembers(filters, limit: 30, offset: 0);
// Query all members
var allMembers = await channel.QueryMembers(new Dictionary<string, object>(), limit: 30, offset: 0);Stream Chat does not run MongoDB on the backend, only a subset of the query options are available.
Query Parameters
| Name | Type | Description | Default | Optional |
|---|---|---|---|---|
| filters | object | The query filters to use. You can query on any of the custom fields defined above | {} | |
| sort | object | The sort parameters | { created_at: 1 } | ✓ |
| options | object | Pagination options | { limit: 100, offset: 0 } | ✓ |
By default, when queryMembers is called without any filter, it matches all members in the channel.
Member Queryable Built-In Fields
The following fields can be used to filter your query results:
| Name | Type | Description | Supported Operators | Example |
|---|---|---|---|---|
| id | string | The ID of the user | $eq, $in | tom |
| name | string | The name of the user | $eq, $in, $autocomplete, $q | Tommaso |
| channel_role | string | The member role | $eq | channel_moderator |
| banned | boolean | The banned status | $eq | false |
| invite | string, must be one of these values: (pending, accepted, rejected) | The status of the invite | $eq | pending |
| joined | boolean | Whether the member has joined the channel | $eq | true |
| created_at | string, must be formatted as an RFC3339 timestamp | The time the member was created | $eq, $gt, $gte, $lt, $lte | 2021-01-15T09:30:20.45Z |
| updated_at | string, must be formatted as an RFC3339 timestamp | The time the member was last updated | $eq, $gt, $gte, $lt, $lte | 2021-01-15T09:30:20.45Z |
| last_active | string, must be formatted as an RFC3339 timestamp | The time the user was last active | $eq, $gt, $gte, $lt, $lte | 2021-01-15T09:30:20.45Z |
| cid | string | The CID of the channel the user is a member of | $eq | messaging:general |
| user.email | string | The email property of the user | $eq, $in, $autocomplete | user@example.com |
You can also filter by any field available in the custom data.
Paginating Channel Members
By default, members are ordered from oldest to newest. You can paginate results using offset-based pagination or by the created_at or user_id fields.
Offset-based pagination is the simplest to implement, but it can lead to incorrect results if the member list changes while you are paginating. The recommended approach is to sort by created_at or user_id.
val channelClient = client.channel("messaging", "general")
val filter = Filters.neutral()
val offset = 0
val limit = 10
// Paginate by user_id in descending order
val sort = QuerySortByField<Member>().descByName("userId")
channelClient.queryMembers(offset, limit, filter, sort).enqueue { result ->
when (result) {
is Result.Success -> {
val members: List<Member> = result.value
}
is Result.Failure -> {
Log.e(TAG, String.format("There was an error %s", result.value), result.value.extractCause())
}
}
}
// Paginate by created_at in ascending order
val createdAtSort = QuerySortByField<Member>().ascByName("createdAt")
channelClient.queryMembers(offset, limit, filter, createdAtSort).enqueue { result ->
when (result) {
is Result.Success -> {
val members: List<Member> = result.value
}
is Result.Failure -> {
Log.e(TAG, String.format("There was an error %s", result.value), result.value.extractCause())
}
}
}// Returns up to 100 members ordered by created_at descending
let sort = { created_at: -1 };
await channel.queryMembers({}, sort, {});
// Returns up to 100 members ordered by user_id descending
sort = { user_id: -1 };
await channel.queryMembers({}, sort, {});
// Paginate by user_id in ascending order
sort = { user_id: 1 };
let options = { user_id_lt: lastMember.user_id };
await channel.queryMembers({}, sort, options);
// Paginate by created_at in descending order
sort = { created_at: -1 };
options = { created_at_before: lastMember.created_at };
await channel.queryMembers({}, sort, options);
// Paginate using offset
options = { offset: 20 };
await channel.queryMembers({}, sort, options);let memberListController = client.memberListController(
query: .init(
cid: .init(type: .messaging, id: "general"),
sort: [.init(key: .createdAt, isAscending: true)]
)
)
memberListController.synchronize() { error in
if error == nil {
memberListController.members
}
}
// Paginate channel members
memberListController.loadNextMembers(limit: 10) { error in
print(error ?? memberListController.members)
}# Paginate by user_id in descending order
response = channel.query_members(
filter_conditions={},
sort=[{"field": "user_id", "direction": 1}],
offset=0,
limit=10,
)
# Paginate by created_at in ascending order
response = channel.query_members(
filter_conditions={},
sort=[{"field": "created_at", "direction": -1}],
offset=0,
limit=10,
)// Paginate channel members
channel.queryMembers(
pagination: PaginationParams(
limit: 10,
offset: 10,
),
);
// Order results by member created_at descending
channel.queryMembers(
sort: [
SortOption(
'created_at',
direction: SortOption.DESC,
),
],
);// Android SDK
ChannelClient channelClient = client.channel("messaging", "general");
int offset = 0;
int limit = 10;
FilterObject filterByName = Filters.neutral();
// Paginate by user_id in descending order
QuerySorter<Member> sort = QuerySortByField.descByName("userId");
channelClient.queryMembers(offset, limit, filterByName, sort, emptyList()).enqueue(result -> {
if (result.isSuccess()) {
List<Member> members = result.data();
} else {
// Handle result.error()
}
});
// Paginate by created_at in ascending order
QuerySorter<Member> createdAtSort = QuerySortByField.ascByName("createdAt");
channelClient.queryMembers(offset, limit, filterByName, createdAtSort, emptyList()).enqueue(result -> {
if (result.isSuccess()) {
List<Member> members = result.data();
} else {
// Handle result.error()
}
});
// Backend SDK
// Paginate by user_id in descending order
ChannelQueryMembersResponse members = Channel.queryMembers()
.sort(Sort.builder().field("user_id").direction(Direction.DESC).build())
.limit(10)
.request();
// Paginate by created_at in ascending order
ChannelQueryMembersResponse members = Channel.queryMembers()
.sort(Sort.builder().field("created_at").direction(Direction.ASC).build())
.limit(10)
.request();# Paginate by user_id in descending order
response = channel.query_members(
filter_conditions: {},
sort: [{ "field" => "user_id", "direction" => 1 }],
offset: 0,
limit: 10,
)
# Paginate by created_at in ascending order
response = channel.query_members(
filter_conditions: {},
sort: [{ "field" => "created_at", "direction" => -1 }],
offset: 0,
limit: 10,
)// Paginate by user_id in descending order
await channelClient.QueryMembersAsync(new QueryMembersRequest
{
FilterConditions = new Dictionary<string, object>(),
Sorts = new[] { new SortParameter { Field = "user_id", Direction = SortDirection.Descending } },
Limit = 10,
Offset = 0,
});
// Paginate by created_at in ascending order
await channelClient.QueryMembersAsync(new QueryMembersRequest
{
FilterConditions = new Dictionary<string, object>(),
Sorts = new[] { new SortParameter { Field = "created_at", Direction = SortDirection.Ascending } },
Limit = 10,
Offset = 0,
});// Paginate by user_id in descending order
$channel->queryMembers(
[],
[["user_id" => 1]],
["limit" => 10, "offset" => 0]
);
// Paginate by created_at in ascending order
$channel->queryMembers(
[],
[["created_at" => -1]],
["limit" => 10, "offset" => 0]
);// Paginate by user_id in descending order
ch.QueryMembers(ctx, &QueryOption{
Filter: make(map[string]interface{}),
Offset: 0,
Limit: 10,
},
&SortOption{Field: "user_id", Direction: 1},
)
// Paginate by created_at in ascending order
ch.QueryMembers(ctx, &QueryOption{
Filter: make(map[string]interface{}),
Offset: 0,
Limit: 10,
},
&SortOption{Field: "created_at", Direction: -1},
)// Returns up to 100 members ordered by created_at descending
{
const TArray<FUserSortOption> Sort{{EUserSortField::CreatedAt, ESortDirection::Descending}};
Channel->QueryMembers({}, Sort, {});
}
// Returns up to 100 members ordered by user_id descending
{
const TArray<FUserSortOption> Sort{{EUserSortField::Id, ESortDirection::Descending}};
Channel->QueryMembers({}, Sort, {});
}
// Paginate by user_id in ascending order
{
const TArray<FUserSortOption> Sort{{EUserSortField::Id, ESortDirection::Ascending}};
FMessagePaginationOptions Options{};
Options.IdLt = LastMember->Id;
Channel->QueryMembers({}, Sort, Options);
}
// Paginate by created_at in ascending order
{
const TArray<FUserSortOption> Sort{{EUserSortField::CreatedAt, ESortDirection::Ascending}};
FMessagePaginationOptions Options{};
Options.CreatedAtBefore = LastMember->CreatedAt;
Channel->QueryMembers({}, Sort, Options);
}
// Paginate using offset
{
const FMessagePaginationOptions Options{
{}, // Limit
20, // Offset
};
Channel->QueryMembers({}, {}, Options);
}var filters = new Dictionary<string, object>
{
{
"id", new Dictionary<string, object>
{
{ "$in", new[] { "user-id-1", "user-id-2" } }
}
}
};
// Pass limit and offset to control the page of results returned
// Limit - how many records per page
// Offset - how many records to skip
var membersResult = await channel.QueryMembers(filters, limit: 30, offset: 0);Pagination Options
| Name | Type | Description | Default | Optional |
|---|---|---|---|---|
| limit | integer | The number of members to return (max is 100) | 100 | ✓ |
| offset | integer | The offset (max is 1000) | 0 | ✓ |
| user_id_lt | string | Pagination option: excludes members with ID greater than or equal to the value | - | ✓ |
| user_id_lte | string | Pagination option: excludes members with ID greater than the value | - | ✓ |
| user_id_gt | string | Pagination option: excludes members with ID less than or equal to the value | - | ✓ |
| user_id_gte | string | Pagination option: excludes members with ID less than the value | - | ✓ |
| created_at_after | string | Pagination option: select members created after the date (RFC3339) | - | ✓ |
| created_at_before | string | Pagination option: select members created before the date (RFC3339) | - | ✓ |
| created_at_before_or_equal | string | Pagination option: select members created before or equal to the date (RFC3339) | - | ✓ |
| created_at_after_or_equal | string | Pagination option: select members created after or equal to the date (RFC3339) | - | ✓ |