Stream Announces $38 Million Series B Funding Learn More →

Querying Members

LAST EDIT Mar 04 2021

Sometimes channels will have many hundreds (or thousands) of members and it is important to be able to access ID's and information on all of these members. The queryMembers endpoint queries the channel members and allows the user to paginate through a full list of users in channels with very large member counts. The endpoint supports filtering on numerous criteria to efficiently return member information.

The members are sorted by created_at in ascending order.
Stream Chat does not run MongoDB on the backend, only a subset of the query options are available.

Here’s some example of how you can query the list of members:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
// query members by user.name 
channel.queryMembers({'name':'tommaso'}) 
 
// query members with name containing tom 
channel.queryMembers({name:{"$q":'tom'}}) 
 
// autocomplete members by user name 
channel.queryMembers({name:{"$autocomplete":'tomm'}}) 
 
// query member by id 
channel.queryMembers({id:'tommaso'}) 
 
// query multiple members by id 
channel.queryMembers({id:{'$in:'['tommaso','thierry']}}) 
 
// query channel moderators 
channel.queryMembers({is_moderator:true}) 
 
// query for banned members in channel 
channel.queryMembers({banned:true}) 
 
// query members with pending invites 
channel.queryMembers({invite:'pending'}) 
 
// query members who joined the channel directly or accepted an invite 
channel.queryMembers({joined: true}) 
 
// query members who has rejected rejected invite or has pending invite 
channel.queryMembers({joined: false} 
 
// query all the members  
channel.queryMembers({}) 
 
// paginate channel members 
channel.queryMembers({}, {}, {limit:10,offset:10}) 
 
// order results by member created at descending 
channel.queryMembers({}, {created_at:-1}) 
 
// query for user.email (currently the only supported custom field) 
client.queryMembers({ 'user.email':'marcelo@getstream.io' }) 
 
// query for user.email field with $autocomplete operator 
channel.queryMembers({ 'user.email':{$autocomplete:'marcelo@get' }}) 
 
// query for user.email with $nin 
client.queryMembers({'user.email':{ $nin:'marcelo@getstream.io' }})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
// > import StreamChat 
 
// 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 
    // handle error / access members 
    print(error ?? controller.members) 
} 
 
// query members with name containing tom 
let controller1 = chatClient.memberListController( 
    query: .init(cid: .init(type: .messaging, id: "general"), filter: .query(.name, text: "tom")) 
) 
 
controller1.synchronize { error in 
    // handle error / access members 
    print(error ?? controller1.members) 
} 
 
// autocomplete members by user name 
let controller2 = chatClient.memberListController( 
    query: .init(cid: .init(type: .messaging, id: "general"), filter: .autocomplete(.name, text: "tom")) 
) 
 
controller2.synchronize { error in 
    // handle error / access members 
    print(error ?? controller2.members) 
} 
 
// query member by id 
let controller3 = chatClient.memberListController( 
    query: .init(cid: .init(type: .messaging, id: "general"), filter: .equal(.id, to: "tommaso")) 
) 
 
controller3.synchronize { error in 
    // handle error / access members 
    print(error ?? controller3.members) 
} 
 
// query multiple members by id 
let controller4 = chatClient.memberListController( 
    query: .init(cid: .init(type: .messaging, id: "general"), filter: .in(.id, values: ["tommaso", "thierry"])) 
) 
 
controller4.synchronize { error in 
    // handle error / access members 
    print(error ?? controller4.members) 
} 
 
// query channel moderators 
let controller5 = chatClient.memberListController( 
    query: .init(cid: .init(type: .messaging, id: "general"), filter: .equal(.isModerator, to: true)) 
) 
 
controller5.synchronize { error in 
    // handle error / access members 
    print(error ?? controller5.members) 
} 
 
// query for banned members in channel 
let controller6 = chatClient.memberListController( 
    query: .init(cid: .init(type: .messaging, id: "general"), filter: .equal(.isBanned, to: true)) 
) 
 
controller6.synchronize { error in 
    // handle error / access members 
    print(error ?? controller6.members) 
} 
 
// query members with pending invites 
let controller7 = chatClient.memberListController( 
    query: .init(cid: .init(type: .messaging, id: "general"), filter: .equal("invite", to: "pending")) 
) 
 
controller7.synchronize { error in 
    // handle error / access members 
    print(error ?? controller7.members) 
} 
 
// query all the members 
let controller8 = chatClient.memberListController( 
    query: .init(cid: .init(type: .messaging, id: "general"), filter: .none) 
) 
 
controller8.synchronize { error in 
    // handle error / access members 
    print(error ?? controller8.members) 
} 
 
// paginate channel members 
controller8.loadNextMembers(limit: 10) { error in 
    // handle error / access members 
    print(error ?? controller8.members) 
} 
 
// order results by member created at descending 
let controller9 = chatClient.memberListController( 
    query: .init(cid: .init(type: .messaging, id: "general"), sort: [.init(key: .createdAt, isAscending: false)]) 
) 
 
controller9.synchronize { error in 
    // handle error / access members 
    print(error ?? controller9.members) 
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# query members by user.name 
response = channel.query_members( 
            filter_conditions={"name": "tommaso"}, 
            sort=[{"field": "created_at", "direction": 1}], 
            offset=1, 
            limit=10, 
        ) 
 
# query members with name containing tom 
response = channel.query_members( filter_conditions={"name": {"$q": "tom"}} ) 
 
# autocomplete members by user name 
response = channel.query_members( filter_conditions={"name": {"$autocomplete": "tomm"}} ) 
 
# query member by id 
response = channel.query_members( filter_conditions={"id": "tommaso"} ) 
 
# query multiple members by id 
response = channel.query_members( filter_conditions={"id": {"$in":['tommaso','thierry']}} ) 
 
# query channel moderators 
response = channel.query_members( filter_conditions={"is_moderator": True} ) 
 
# query for banned members in channel 
response = channel.query_members( filter_conditions={"banned": True}) 
 
# query members with pending invites 
response = channel.query_members( filter_conditions={"invite": "pending"} )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
val channelClient = client.channel("messaging", "general") 
 
val offset = 0 // Use this value for pagination 
val limit = 10 
val sort = QuerySort<Member>() 
 
// Channel members can be queried with various filters 
// 1. Create the filter, e.g query members by user name 
val filterByName = Filters.eq("name", "tommaso") 
// 2. Call queryMembers with that filter 
channelClient.queryMembers(offset, limit, filterByName, sort).enqueue { result -> 
    if (result.isSuccess) { 
        val members: List<Member> = result.data() 
    } else { 
        Log.e(TAG, String.format("There was an error %s", result.error()), result.error().cause) 
    } 
} 
 
// Here are some other commons filters you can use: 
 
// Autocomplete members by user name (names containing "tom") 
val filterByAutoCompleteName = Filters.autocomplete("name", "tom") 
 
// Query member by id 
val filterById = Filters.eq("id", "tommaso") 
 
// Query multiple members by id 
val filterByIds = Filters.`in`("id", listOf("tommaso", "thierry")) 
 
// Query channel moderators 
val filterByModerator = Filters.eq("is_moderator", true) 
 
// Query for banned members in channel 
val filterByBannedMembers = Filters.eq("banned", true) 
 
// Query members with pending invites 
val filterByPendingInvite = Filters.eq("invite", "pending") 
 
// Query all the members 
val filterByNone = FilterObject() 
 
// Results can also be orderd with the QuerySort param 
// For example, this will order results by member creation time, descending 
val createdAtDescendingSort = QuerySort<Member>().desc("created_at")
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
ChannelClient channelClient = client.channel("messaging", "general"); 
 
int offset = 0; // Use this value for pagination 
int limit = 10; 
QuerySort<Member> sort = new QuerySort<>(); 
 
// Channel members can be queried with various filters 
// 1. Create the filter, e.g query members by user name 
FilterObject filterByName = Filters.eq("name", "tommaso"); 
// 2. Call queryMembers with that filter 
channelClient.queryMembers(offset, limit, filterByName, sort, emptyList()).enqueue(result -> { 
    if (result.isSuccess()) { 
        List<Member> members = result.data(); 
    } else { 
        // Handle result.error() 
    } 
}); 
 
// Here are some other commons filters you can use: 
 
// Autocomplete members by user name (names containing "tom") 
FilterObject filterByAutoCompleteName = Filters.autocomplete("name", "tom"); 
 
// Query member by id 
FilterObject filterById = Filters.eq("id", "tommaso"); 
 
// Query multiple members by id 
FilterObject filterByIds = Filters.in("id", Arrays.asList("tommaso", "thierry")); 
 
// Query channel moderators 
FilterObject filterByModerator = Filters.eq("is_moderator", true); 
 
// Query for banned members in channel 
FilterObject filterByBannedMembers = Filters.eq("banned", true); 
 
// Query members with pending invites 
FilterObject filterByPendingInvite = Filters.eq("invite", "pending"); 
 
// Query all the members 
FilterObject filterByNone = new FilterObject(); 
 
// We can order the results too with QuerySort param 
// Here example to order results by member created at descending 
QuerySort<Member> createdAtDescendingSort = new QuerySort<Member>().desc("created_at");
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
// query members by user.name 
channel.queryMembers( 
  filter: { 
    'name': 'tommaso', 
  }, 
); 
 
// query members with name containing tom 
channel.queryMembers( 
  filter: { 
    'name': { 
      r'$q': 'tom', 
    }, 
  }, 
); 
// autocomplete members by user name 
channel.queryMembers( 
  filter: { 
    'name': { 
      r'$autocomplete': 'tomm', 
    }, 
  }, 
); 
 
// query member by id 
channel.queryMembers( 
  filter: { 
    'id': 'tommaso', 
  }, 
); 
 
// query multiple members by id 
channel.queryMembers( 
  filter: { 
    'id': { 
      r'$in': [ 
        'tommaso', 
        'thierry', 
      ], 
    }, 
  }, 
); 
 
// query channel moderators 
channel.queryMembers( 
  filter: { 
    'is_moderator': true, 
  }, 
); 
 
// query for banned members in channel 
channel.queryMembers( 
  filter: { 
    'banned': true, 
  }, 
); 
 
// query members with pending invites 
channel.queryMembers( 
  filter: { 
    'invite': 'pending', 
  }, 
); 
 
// query all the members  
channel.queryMembers(); 
 
// 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, 
   ), 
  ], 
); 
 
// query for user.email (currently the only supported custom field) 
channel.queryMembers( 
  filter: { 
    'email': 'marcelo@getstream.io', 
  }, 
); 
 
// query for user.email field with $autocomplete operator 
channel.queryMembers( 
  filter: { 
    'email': { 
      r'$autocomplete': 'marcelo@getstr', 
    }, 
  }, 
); 
 
 
// query for user.email with $nin 
channel.queryMembers( 
  filter: { 
    'email': { 
      r'$nin': 'marcelo@getstream.io', 
    }, 
  }, 
);

Query Parameters

Copied!
nametypedescriptiondefaultoptional
filtersobjectThe query filters to use. You can query on any of the custom fields defined above{}
sortobjectthe sort parameters{ created_at:1}
optionsobjectpagination options{ limit:100, offset:0}
By default when query members does not have any filter and it will match all members on your channel.

Member Queryable Built-In Fields

Copied!

The following channel fields can be used to filter your query results

Name

Type

Description

Example

id

string

the id of the user

tom

name

string

the name of the user

Tommaso

is_moderator

boolean

the member role

true

banned

boolean

the banned status

false

invite

string, must be one of these values: (pending, accepted, rejected)

the status of the invite

pending

joined

boolean

whether member is joined the channel or not

true

Query Options

Copied!
nametypedescriptiondefaultoptional
limitintegerThe number of members to return (max is 100)100
offset integer The offset (max is 1000)0

Response

Copied!

The result of query Members is a  QueryMembersResponse object which include all the matched members within the limit

QueryMembersResponse

Copied!

Field Name

Description

members

The list of members, up to 100 ordered by the most recent added