Reputation: 15
I found a sample on the internet for loading documents from Azure Cosmos DB with SQL API. It appears to load all the documents first then the .Where and the .OrderBy are applied after. Is there a way the 'GetItemsAsync' method can be rewritten so that the code below would work without loading the whole collection first?
Is there a way to call the 'GetItemsAsync' method in this manner?
foreach(Member pMember in GetItemsAsync<Member>()
.Where(m=> m.Name == "Mike").OrderBy(m=> m.LastName))
{
}
Would .AsEnumerable work?
public static async Task<IEnumerable<T>> GetItemsAsync()
{
IDocumentQuery<T> query = _documentClient.CreateDocumentQuery<T>(
UriFactory.CreateDocumentCollectionUri(DatabaseId,CollectionId),
new FeedOptions { MaxItemCount = -1 }).AsDocumentQuery();
List<T> results = new List<T>();
while (query.HasMoreResults)
{
results.AddRange(await query.ExecuteNextAsync<T>());
}
return results;
}
or am I forced to structure it like this: with the predicate as a parameter in the method?
public static async Task<IEnumerable<T>> GetItemsAsync(Expression<Func<T, bool>> predicate)
{
IDocumentQuery<T> query = _documentClient.CreateDocumentQuery<T>(
UriFactory.CreateDocumentCollectionUri(DatabaseId, CollectionId),
new FeedOptions { MaxItemCount = -1 })
.Where(predicate).AsDocumentQuery();
List<T> results = new List<T>();
while (query.HasMoreResults)
{
results.AddRange(await query.ExecuteNextAsync<T>());
}
return results;
}
Upvotes: 1
Views: 1317
Reputation: 943
I think you have to use the second method, the one with the predicate as a parameter.
To execute a query without loading everything from the database, you would need an IQueryable
rather than an IEnumerable
. And to execute it asynchronously, you would need IDocumentQuery
as it is mentioned here
Specifically, to implement the form of foreach
that you want to achieve, you can do something like the following example.
Get an IQueryable
public static IQueryable<T> GetItemsQueryable<T>()
{
IQueryable<T> query = client.CreateDocumentQuery<T>(
collection.SelfLink,
new FeedOptions { MaxItemCount = -1 })
.AsQueryable<T>();
return query;
}
Then use it like below:
foreach (var item in GetItemsQueryable<DeviceReading>()
.Where(m => m.MetricType == "Temperature" && m.DeviceId == "XMS-0001")
.OrderBy(m => m.MetricValue))
{
Console.WriteLine(item.MetricValue);
}
Upvotes: 1