user2638032
user2638032

Reputation: 15

Linq style query for CreateDocumentQuery<T> Where OrderBy

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

Answers (1)

Chun Liu
Chun Liu

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

Related Questions