Reputation: 3911
I have a document db collection that contains about 1500 docs. My eventual goal is to build an api with the above as my persistence layer. I read the docs (https://azure.microsoft.com/en-us/blog/documentdb-paging-support-with-top-and-more-query-improvements/) that mentions to use request continuation token via feed options for paging.
Have the following method on a console app to understand the same: The problem or the issue here is that the first time the query is executed the continuation token=null but the second time the query is executed the continuation token = "some value"
So my question is shouldn't the continuation token be set the first time itself? or am I missing something obvious
//field
private static readonly FeedOptions DefaultOptions = new FeedOptions { EnableCrossPartitionQuery = true,MaxItemCount = 1};
//method
private static async Task<bool> QueryItemDocuments(string collectionLink)
{
IDocumentQuery<Item> query = client.CreateDocumentQuery<Item>(collectionLink, new SqlQuerySpec()
{
QueryText = "SELECT * FROM items",
},DefaultOptions).AsDocumentQuery();
var loopNumber = 0;
while (query.HasMoreResults)
{
loopNumber++;
var results=(await query.ExecuteNextAsync<Item>()).ToList();
Console.WriteLine("Count {0}",results.Count);
Console.WriteLine("Loopnumber :{0} Token {1}", loopNumber, DefaultOptions.RequestContinuation ?? "Null");
Console.WriteLine("Id: {0},Name: {1}", results[0].Id, results[0].Name);
}
return query.HasMoreResults;
}
sample results from console :
Count 1
Loopnumber :1 Token Null //why is this null?
Id: 1dbaf1d0-0125-11e0-88a8-005056957023,Name:Energy Drink
Count 1
Loopnumber :2 Token - RID:jq4gAIZqMwACBBBBBBB==#RT:1#TRC:1#PKRID:0
Id: 244a8230-0231-11e0-8c8b-005056957023,Name: Gluten Free Dish
Edits: Ideally, I would send back the continuation token on the response headers allowing the client to fetch more if needed (on my web api) - so my method would like
public Get(int? page=1,int? size=20)
so when I send the response back with the first 20 I need to send back the continuation token for the client to request more: so if the continuation token is not set the first time - meaning when I retrieve the 1st batch of 20, how do I do this?
Upvotes: 1
Views: 3245
Reputation: 3911
okay, so i figured that it might be a bug in the SDK or by design - do not know, however when I query for the result using Document Db's rest end points
- the continuation token
is indeed set on the first batch's response. Here is the sample code that used:
private static async Task QueryItemDocumentsUsingRestApi()
{
//About rest end points to query documents here https://msdn.microsoft.com/en-us/library/azure/mt670897.aspx
IEnumerable<string> continuationTokens = null;
var continToken = string.Empty;
var verb = "POST";
var resourceType = "docs";
var resourceLink = string.Format("dbs/{0}/colls/{1}/docs", DatabaseName, CollectionName);
var resourceId = string.Format("dbs/{0}/colls/{1}", DatabaseName, CollectionName)
var authHeader = GenerateAuthSignature(verb, resourceId, resourceType, authorizationKey, "master", "1.0"); // look here for how this is generated https://github.com/Azure/azure-documentdb-dotnet/blob/master/samples/rest-from-.net/Program.cs
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Add("x-ms-date", _utcDate);
client.DefaultRequestHeaders.Add("x-ms-version", "2015-08-06");
client.DefaultRequestHeaders.Remove("authorization");
client.DefaultRequestHeaders.Add("authorization", authHeader);
client.DefaultRequestHeaders.Add("x-ms-documentdb-isquery", "True");
client.DefaultRequestHeaders.Add("x-ms-max-item-count", "5");
client.DefaultRequestHeaders.Add("x-ms-continuation", string.Empty);
var qry = new RestSqlQuery { query = "SELECT * FROM items" };
var result = client.PostWithNoCharSetAsync(new Uri(new Uri(endpointUrl), resourceLink), qry).Result;
var content = await result.Content.ReadAsStringAsync();
var pagedList = JsonConvert.DeserializeObject<PagedList>(content);
if (result.Headers.TryGetValues("x-ms-continuation", out continuationTokens))
{
continToken = continuationTokens.FirstOrDefault();
}
}
}
Upvotes: 0
Reputation: 9523
You are on the right track. Two thoughts:
You don't need to manually process the continuation token when using HasMoreResults
and ExecuteNext
. HasMoreResults
checks if there is a continuation token and when you call ExecuteNext
, it's automatically added.
I suspect that the reason you don't see a continuation on the first round is that it's the outgoing DefaultOptions
and it's not updated until it goes out again on the second ExecuteNext
. I'm thinking that your output on the second loop is actually the first continuation token.
Upvotes: 1