ABCD
ABCD

Reputation: 399

How to reduce the loading time

I am updating a product within category, but my query loading time is 4.32s. But cosmos db is read pass. Is there any way to reduce time? Please suggest me any idea.

For the first load it takes around 5s, then it takes 3-4.5 seconds. Is there any way to solve this issue?

My repository class code :

public async Task<Catalog> UpdateProductInMainCategory(Guid productid, Product productData)
{
    var feedOptions = new FeedOptions
     {
         MaxItemCount = -1,
         EnableCrossPartitionQuery = true
     };

    var query =
        $"SELECT catalog.id,catalog.VendorName,catalog.Industy,product1 FROM catalog join industry in catalog.Industy join category in industry.Category join product1 in category.Product join Subcategory in category.Subcategory join product in Subcategory.Product where product1.Id ='" + productid + "'";

    var catlog = _cosmosClient.CreateDocumentQuery<Catalog>(UriFactory.CreateDocumentCollectionUri(
    _azureCosmosDbOptions.Value.DatabaseId, "catalog"), query, feedOptions).AsEnumerable().FirstOrDefault();

    Console.WriteLine("i am kajas");

    if (catlog != null)
    {
        foreach (var item in catlog.Industy)
        {
            foreach (var cat in item.Category)
            {
                Product product = cat.Product.FirstOrDefault(p => p.Id == productid);
                if (product != null)
                {
                    product.Name = productData.Name == null ? product.Name : productData.Name;
                    product.Addons = productData.Addons == null ? product.Addons : productData.Addons;
                    product.CurrentQuantity = 
                    break;
                }

            }
            break;
        }
    }
    var requestOptions = new RequestOptions
      {
          PartitionKey = new Microsoft.Azure.Documents.PartitionKey(catlog.Id.ToString())
      };

    var orderDocument = await _cosmosClient.ReplaceDocumentAsync(
         UriFactory.CreateDocumentUri(
             _azureCosmosDbOptions.Value.DatabaseId, "catalog", catlog.Id.ToString()), catlog, requestOptions);

    return (Catalog)((dynamic)catlog);
}

Upvotes: 1

Views: 62

Answers (1)

Nick Chapsas
Nick Chapsas

Reputation: 7200

You are also setting the MaxItemCount to -1 and you are using AsEnumerable().FirstOrDefault(). This means that you will force the system to return everything in a single page. However, this is not recommended. On top of that I can see that you aren't using the ExecuteNextAsync approach.

Rewriting your code should looks something like this:

public async Task<Catalog> UpdateProductInMainCategory(Guid productid, Product productData)
{
    var feedOptions =
     new FeedOptions
     {
         MaxItemCount = 100,
         PartitionKey = new PartitionKey(productid.ToString())
     };

    var query =
        $"SELECT catalog.id,catalog.VendorName,catalog.Industy,product1 FROM catalog join industry in catalog.Industy join category in industry.Category join product1 in category.Product join Subcategory in category.Subcategory join product in Subcategory.Product where product1.Id ='" + productid + "'";

    var catlogQuery = _cosmosClient.CreateDocumentQuery<Catalog>(UriFactory.CreateDocumentCollectionUri(_azureCosmosDbOptions.Value.DatabaseId, "catalog"), query, feedOptions).AsDocumentQuery();

    Catalog catalog = null;

    while(catlogQuery.HasMoreResults)
    {
        var result = await catlogQuery.ExecuteNextAsync();
        if(result.Any())
        {
            catalog = result;
            break;
        }
    }

    Console.WriteLine("i am kajas");

    if (catlog != null)
    {
        foreach (var item in catlog.Industy)
        {
            foreach (var cat in item.Category)
            {
                Product product = cat.Product.FirstOrDefault(p => p.Id == productid);
                if (product != null)
                {
                    product.Name = productData.Name == null ? product.Name : productData.Name;
                    product.Addons = productData.Addons == null ? product.Addons : productData.Addons;
                    product.CurrentQuantity = 
                    break;
                }

            }
            break;
        }
    }
    var requestOptions =
      new RequestOptions
      {
          PartitionKey = new Microsoft.Azure.Documents.PartitionKey(catlog.Id.ToString())
      };

    var orderDocument = await _cosmosClient.ReplaceDocumentAsync(
         UriFactory.CreateDocumentUri(
             _azureCosmosDbOptions.Value.DatabaseId, "catalog", catlog.Id.ToString()), catlog, requestOptions);



    return (Catalog)((dynamic)catlog);
}

Notice that now it will go though the proper pagination process and it will exit faster because it won't lock your thread which it's querying and also return when it has a first match in the while loop.

On a side note, it looks like your code could benefit by using Cosmonaut. It offers a lot of this functionality out of the box. This same query would look like this:

var query =
        $"SELECT catalog.id,catalog.VendorName,catalog.Industy,product1 FROM catalog join industry in catalog.Industy join category in industry.Category join product1 in category.Product join Subcategory in category.Subcategory join product in Subcategory.Product where product1.Id ='" + productid + "'";

var catalog = await _catalogStore.Query(query).FirstOrDefaultAsync();

Full disclosure, I'm the creator of Cosmonaut.

Upvotes: 1

Related Questions