val channelClient = client.channel("messaging", "general")
val pageSize = 10
// Request for the first page
val request = QueryChannelRequest()
.withMessages(pageSize)
channelClient.query(request).enqueue { result ->
if (result.isSuccess) {
val messages: List<Message> = result.data().messages
if (messages.size < pageSize) {
// All messages loaded
} else {
// Load next page
val nextRequest = QueryChannelRequest()
.withMessages(LESS_THAN, messages.last().id, pageSize)
// ...
}
} else {
// Handle result.error()
}
}
Channel Pagination
The channel query endpoint allows you to paginate the list of messages, watchers, and members for one channel. To make sure that you are able to retrieve a consistent list of messages, pagination does not work with simple offset/limit parameters but instead, it relies on passing the ID of the messages from the previous page.
For example: say that you fetched the first 100 messages from a channel and want to load the next 100. To do this you need to make a channel query request and pass the ID of the oldest message if you are paginating in descending order or the ID of the newest message if paginating in ascending order.
Use the id_lt
parameter to retrieve messages older than the provided ID and id_gt
to retrieve messages newer than the provided ID.
The terms id_lt
and id_gt
stand for *ID less than and ID greater than. *
ID-based pagination improves performance and prevents issues related to the list of messages changing while you’re paginating. If needed, you can also use the inclusive versions of those two parameters: id_lte
and id_gte
.
// the id of the last message on the page
const lastMessageId = messages[0].id;
// pick the parts you need; messages, members or watchers
const result = await channel.query({
messages: { limit: 20, id_lt: lastMessageId } ,
members: { limit: 20, offset: 0 } ,
watchers: { limit: 20, offset: 0 },
});
// fetch messages around a specific message
const result = await channel.query({
messages: { limit: 20, id_around: message_id }
});
final response = await channel.query(
messagesPagination: PaginationParams(limit: 2, lessThanOrEqual: "123"),
membersPagination: PaginationParams(limit: 2, offset: 0),
watchersPagination: PaginationParams(limit: 2, offset: 0),
);
$messages = $channel->query([
'messages' => ['limit'=>2, 'id_lte' => '123'],
'members' => ['limit'=>2, 'offset' => 0],
'watchers' => ['limit'=>2, 'offset' => 0]
]);
let messageId: MessageId = "123"
let channelId = ChannelId(type: .messaging, id: "general")
let controller = chatClient.channelController(for: channelId)
// Equals to id_around
controller.loadPageAroundMessageId(messageId) { error in
if let error = error {
// handle error
print(error)
} else {
// access messages
print(controller.messages)
// Equals to id_gt (where id is the newest fetched message id)
controller.loadNextMessages(limit: 10) { error in
// handle error / access messages
print(error ?? controller.messages)
// Equals to id_lt (where id is the oldest fetched message id)
controller.loadPreviousMessages(limit: 10) { error in
print(error ?? controller.messages)
}
}
}
}
// `Chat` provides more granual access
let chat = chatClient.makeChat(for: channelId)
// Messages for id_gt
let greaterThanPagination = MessagesPagination(
pageSize: 10,
parameter: .greaterThan(messageId)
)
let messagesGreaterThan = try await chat.loadMessages(with: greaterThanPagination)
// Messages for id_lt
let lessThanPagination = MessagesPagination(
pageSize: 10,
parameter: .lessThan(messageId)
)
let messagesLessThan = try await chat.loadMessages(with: lessThanPagination)
// Message around a message id
let aroundPagination = MessagesPagination(
pageSize: 10,
parameter: .around(messageId)
)
let messagesAround = try await chat.loadMessages(with: aroundPagination)
// And also convenience methods
try await chat.loadMessages(before: messageId, limit: 10)
try await chat.loadMessages(around: messageId, limit: 10)
try await chat.loadMessages(after: messageId, limit: 10)
let loadedMessages = chat.state.messages
# the id of the last message on the page
last_message_id = messages[0]["id"]
# pick the parts you need; messages, members or watchers
result = channel.query(
messages={"limit": 50, "id_lt": last_message_id},
members={"limit": 10, "offset": 0},
watchers={"limit": 20, "offset": 0},
)
# the id of the last message on the page
last_message_id = messages[0]["id"]
# pick the parts you need; messages, members or watchers
result = channel.query({
'messages' => {'limit' => 50, 'id_lt' => last_message_id},
'members' => {'limit' => 50, 'offset' => 0},
'watchers' => {'limit' => 50, 'offset' => 0},
})
FMessagePaginationOptions MessagesPagination;
MessagesPagination.Limit = 2;
MessagesPagination.IdLte = TEXT("123");
const FUserPaginationOptions MemberPagination{2, 0};
const FUserPaginationOptions WatcherPagination{2, 0};
Channel->Query(EChannelFlags::State, MessagesPagination, MemberPagination, WatcherPagination);
// the id of the last message on the page
var lastMessageId = messages[0].Id;
// pick the parts you need; messages, members or watchers
await channelClient.GetOrCreateAsync("messaging", "general", new ChannelGetRequest
{
MessagesPagination = new MessagePaginationParams { Limit = 50, IDLT = lastMessageId },
MembersPagination = new PaginationParams { Limit = 10, Offset = 0 },
WatchersPagination = new PaginationParams { Limit = 20, Offset = 0 },
});
// the id of the last message on the page
lastMessageId := messages[0].Id
// pick the parts you need; messages, members or watchers
options := map[string]interface{}{
"messages": map[string]interface{}{"limit": 50, "id_lt": lastMessageId},
"members": map[string]interface{}{"limit": 10, "offset": 0},
"watchers": map[string]interface{}{"limit": 20, "offset": 0},
}
ch.query(ctx, options, nil)
// Android SDK
ChannelClient channelClient = client.channel("messaging", "general");
int pageSize = 10;
// Request for the first page
QueryChannelRequest request = new QueryChannelRequest()
.withMessages(pageSize);
channelClient.query(request).enqueue(result -> {
if (result.isSuccess()) {
List<Message> messages = result.data().getMessages();
if (messages.size() < pageSize) {
// All messages loaded
} else {
// Load next page
Message lastMessage = messages.get(messages.size() - 1);
QueryChannelRequest nextRequest = new QueryChannelRequest()
.withMessages(LESS_THAN, lastMessage.getId(), pageSize);
// ...
}
} else {
// Handle result.error()
}
});
// Backend SDK
String lastMessageId = lastMessage.getId();
ChannelGetResponse resp = Channel.getOrCreate("type", "id")
.messages(
MessagePaginationParameters
.builder()
.idLt(lastMessageId)
.build())
.request()
// Use resp.getMessages() somehow
// Channel is loaded with the most recent messages
var channel = await Client.GetOrCreateChannelWithIdAsync(ChannelType.Messaging, channelId: "my-channel-id");
// Every call will load 1 more page of messages
await channel.LoadOlderMessagesAsync();
For members and watchers, we use limit
and offset
parameters. The maximum limit and offset that can be used is 300
and 10000
, respectively.
Soon we will create friendlier aliases for id_lt and id_gt. Our best candidates are before_id and after_id, let us know if you have any feedback or suggestion!
The maximum number of messages that can be retrieved at once from the API is 300.