Pagination in Cosmos DB using Page Size and Page Number
Skip & take is now available in Cosmos DB via a new OFFSET LIMIT clause: https://docs.microsoft.com/en-us/azure/cosmos-db/sql-query-offset-limit
Currently, the pagination support is based on continuation token only.
Find below some interesting discussion and feature request about this limitation:
- https://github.com/Azure/azure-documentdb-dotnet/issues/377
- https://feedback.azure.com/forums/263030-azure-cosmos-db/suggestions/6350987--documentdb-allow-paging-skip-take
--- Continuation Token Example ---
The following example illustrates a method (very similar to yours) that queries documents based on the desired page number, page size and continuation token:
private static async Task<KeyValuePair<string, IEnumerable<CeleryTask>>> QueryDocumentsByPage(int pageNumber, int pageSize, string continuationToken)
{
DocumentClient documentClient = new DocumentClient(new Uri("https://{CosmosDB/SQL Account Name}.documents.azure.com:443/"), "{CosmosDB/SQL Account Key}");
var feedOptions = new FeedOptions {
MaxItemCount = pageSize,
EnableCrossPartitionQuery = true,
// IMPORTANT: Set the continuation token (NULL for the first ever request/page)
RequestContinuation = continuationToken
};
IQueryable<CeleryTask> filter = documentClient.CreateDocumentQuery<CeleryTask>("dbs/{Database Name}/colls/{Collection Name}", feedOptions);
IDocumentQuery<CeleryTask> query = filter.AsDocumentQuery();
FeedResponse<CeleryTask> feedRespose = await query.ExecuteNextAsync<CeleryTask>();
List<CeleryTask> documents = new List<CeleryTask>();
foreach (CeleryTask t in feedRespose)
{
documents.Add(t);
}
// IMPORTANT: Ensure the continuation token is kept for the next requests
return new KeyValuePair<string, IEnumerable<CeleryTask>>(feedRespose.ResponseContinuation, documents);
}
Now, the following example illustrates how to retrieve documents for a given page by calling the previous method:
private static async Task QueryPageByPage()
{
// Number of documents per page
const int PAGE_SIZE = 3;
int currentPageNumber = 1;
int documentNumber = 1;
// Continuation token for subsequent queries (NULL for the very first request/page)
string continuationToken = null;
do
{
Console.WriteLine($"----- PAGE {currentPageNumber} -----");
// Loads ALL documents for the current page
KeyValuePair<string, IEnumerable<CeleryTask>> currentPage = await QueryDocumentsByPage(currentPageNumber, PAGE_SIZE, continuationToken);
foreach (CeleryTask celeryTask in currentPage.Value)
{
Console.WriteLine($"[{documentNumber}] {celeryTask.Id}");
documentNumber++;
}
// Ensure the continuation token is kept for the next page query execution
continuationToken = currentPage.Key;
currentPageNumber++;
} while (continuationToken != null);
Console.WriteLine("\n--- END: Finished Querying ALL Dcuments ---");
}