Skip to content

Instantly share code, notes, and snippets.

@rasmuschristensen
Created August 18, 2019 13:53
Show Gist options
  • Save rasmuschristensen/81d4e4694b4993765c3ad36d8f45fd36 to your computer and use it in GitHub Desktop.
Save rasmuschristensen/81d4e4694b4993765c3ad36d8f45fd36 to your computer and use it in GitHub Desktop.
CosmosDb Async Exists support
public static class ContainerExtensions
{
public static async Task<bool> ExistsAsync<T>(this Container container, Expression<Func<T,bool>> predicate)
{
var qdef = container.GetItemLinqQueryable<T>().Where(predicate).ToQueryDefinition();
var iterator = container.GetItemQueryIterator<T>(qdef.QueryText, null, new QueryRequestOptions { MaxItemCount = 1 });
if (!iterator.HasMoreResults) return false;
var response = await iterator.ReadNextAsync();
return response.FirstOrDefault() != null;
}
}
@j82w
Copy link

j82w commented Aug 22, 2019

Results are not guaranteed to be on the first page. There is several scenarios where the first page will be empty. You should drain all the results to verify that one of the following pages doesn't have a result.

while(iterator.HasMoreResults){

var response = await iterator.ReadNextAsync();
if(response.FirstOrDefault() != null){
    return true;
}
}
return false;

@rasmuschristensen
Copy link
Author

Interesting I wasn't aware of that. what kind of scenarios would that be?

@j82w
Copy link

j82w commented Aug 23, 2019

The easiest example I can think of is if you have a cross partition query where the container has 3 physical partitions in Cosmos DB. You say " select * from T where T.cost > 100". The first partition might have 0 items that match that query. So it will return a page with 0 items. In the next ReadNextAsync it will go to partition 2 and it also has 0 items. ReadNextAsync is called again and the 3rd partition return 10 items.

@rasmuschristensen
Copy link
Author

Okay I get what you're saying. If I specify a partitionkey it would work with out empty results right?

@j82w
Copy link

j82w commented Aug 24, 2019

It's less likely but it's still possible with a PartitionKey. The one example with a partition key is "skip 100,000" items is likely to cause the first page to be empty. It is possible to get an empty page due to the backend preempting your query. This would mean that your query is taking more than some fixed amount of time on the backend to retrieve your documents, so it preempts your query and sends you a continuation if you want to continue making progress on the query.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment