-
Notifications
You must be signed in to change notification settings - Fork 494
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support for CountAsync() #589
Comments
The way you can do this in v3 is by using the ToFeedIterator method.
|
That solution is not as clean as CountAsync(). Possible solutions:
|
@j82w Thanks for the response. We had a quick test with your above suggestion and had some interesting observations to share. Test Scenarios:
Test Code var feedOptions = new FeedOptions
{
MaxBufferedItemCount = -1,
MaxItemCount = -1,
MaxDegreeOfParallelism = -1,
EnableCrossPartitionQuery = true
};
var documentClientSyncCount = documentClient.CreateDocumentQuery<Image>(uri, feedOptions)
.Count(x => x.Investigations.Contains(investigationKey));
Console.WriteLine($"DocumentClient.Count: {documentClientSyncCount} - {watch.Elapsed.TotalMilliseconds:0}ms");
watch.Restart();
var documentClientAsyncCount = await documentClient.CreateDocumentQuery<Image>(uri, feedOptions)
.Where(x => x.Investigations.Contains(investigationKey)).CountAsync();
Console.WriteLine($"DocumentClient.CountAsync: {documentClientAsyncCount} - {watch.Elapsed.TotalMilliseconds:0}ms");
watch.Restart();
var queryRequestOptions = new QueryRequestOptions
{
MaxBufferedItemCount = -1,
MaxConcurrency = -1,
MaxItemCount = -1
};
var cosmosSyncCount = imagesContainer.GetItemLinqQueryable<Image>(true, queryRequestOptions).Count(x => x.Investigations.Contains(investigationKey));
Console.WriteLine($"CosmosClient.Count: {cosmosSyncCount} - {watch.Elapsed.TotalMilliseconds:0}ms");
watch.Restart();
var cosmosAsyncCount = 0;
var countIterator = imagesContainer.GetItemLinqQueryable<Image>(false, queryRequestOptions).Where(x => x.Investigations.Contains(investigationKey))
.ToFeedIterator();
while (countIterator.HasMoreResults)
{
var response = await countIterator.ReadNextAsync();
cosmosAsyncCount += response.Resource.Count();
}
Console.WriteLine($"CosmosClient.CountAsync: {cosmosAsyncCount} - {watch.Elapsed.TotalMilliseconds:0}ms"); Results
Observations
We ran in to this issue as we are attempting to port our current 2.x SDK code to the new 3.x SDK. From this perspective, we have a large number of cases where we wish to perform various counts to a number of collections and we will often firing these off using If it was possible, we'd love to see your proposal of |
@wahyuen is your only goal to get a count or do you eventually need to use the items? CosmosClient.Count isn't returning the objects. It's only returning a count.
|
Regarding the extension method we would really like to avoid it. Extension methods can't be mocked. It also can lead to confusion in some cases since it shows up on all IQueryable instead of just the Cosmos ones. |
@j82w in the context of the queries where we are using the counts, we only need to deal with the number itself and don't interact or interate the actual items themselves. Given that, anything where we can simply have the database server optimally return the count without having to transfer the items themselves would be ideal in this situation. In the current version, I don't think we can rewrite the query to the form you described above? The Slightly outside of this ticket, but perhaps related, in the 2.x SDK we relied quite alot on the extension methods found inside |
Sorry, I should have tested that before posting. I forgot count executes the query. Thanks for bringing this gap to my attention. We will come up with a plan to unblock these scenarios. We might end up just adding the extensions methods, but I would really like to find a more unit test friendly path. |
Hitting the exact same issue upgrading from v2 to v3. Previously using the CountAsync() method after applying a "where" predicate.
Iterating over the documents and summing the count up seems less than ideal (and RU costly) when the final count is the only thing needed. The predicate condition spans multiple partitions so a stored procedure would also not be viable. With the ability to convert a LINQ query to SQL query string I could replace the initial portion of the string "select *" with a "select value count(1)" for a query only containing the where portion. This seems like a hacky workaround though. |
With the newly released 3.1 SDK I'm now able to work around this issue with the following code.
|
I'm in need of the same, just to check if something exists. I created this extension. Similar to could be made to support count https://gist.github.com/rasmuschristensen/81d4e4694b4993765c3ad36d8f45fd36 |
Fixed in #729 |
@simplynaveen20 @j82w Regarding #729, are the async methods slower than sync methods still? Have you worked on performance improvements? |
@petro2050 can you create a new issue with how you are doing the call and the perf you are seeing? |
Is your feature request related to a problem? Please describe.
In version 2.x of the SDK, we were able to execute asynchronous calls for determining the count of a
IQueryable
. It seems like you can only perform this in a synchronous fashion in the current version of the SDK.Describe the solution you'd like
Support the
CountAsync()
LINQ syntaxDescribe alternatives you've considered
None, there doesn't appear to be support for this currently.
The text was updated successfully, but these errors were encountered: