question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

GetItemQueryStreamIterator API Name, Casing, and Sample Issues

See original GitHub issue

Following the docs here: https://docs.microsoft.com/en-us/dotnet/api/azure.cosmos.cosmoscontainer.getitemquerystreamiterator?view=azure-dotnet-preview

I was expecting this code:

public class ToDoActivity{
    public string id {get; set;}
    public string status {get; set;}
    public int cost {get; set;}
}

QueryDefinition queryDefinition = new QueryDefinition("select * from ToDos t where t.cost > @expensive")
    .WithParameter("@expensive", 9000);
await foreach(Response response in this.Container.GetItemQueryStreamIterator(
                                                queryDefinition,
                                                null,
                                                new QueryRequestOptions() { PartitionKey = new PartitionKey("Error")}))
    {
        using (StreamReader sr = new StreamReader(response.Content))
        using (JsonTextReader jtr = new JsonTextReader(sr))
        {
            JObject result = JObject.Load(jtr);
        }
    }

To return each Document inside of the await foreach loop.

But, it actually returns a structure like this:

{
  "Documents": []
}

So, I had to create a class like this:

    public class QueryStream
    {
        [JsonPropertyName("Documents")]
        public QueueMessage[] Documents { get; set; }
    }

And then deserialize using that class.

Issue # 1: “Documents” casing

Because “Documents” is Pascal casing it will conflict with my SerializationOptions and child documents, which have camelCasing.

Question: Should we use “documents” instead or enable the user to specify casing for the outer documents. Or ask users to name their property “public QueueMessage[] documents” so the casing is honor. As you can see above I needed to add a JsonPropertyNames attribute, because I’m deserializing with camel and so it expects Documents to be camel as well.

Issue # 2: API name

Based on the example and the API name, I was expecting it to yield for every document, not every page.

Question: Should this be renamed to GetItemPageQueryStreamIterator?

Issue # 3: Docs are misleading.

Because the doc has a single item class ToDoActivity, I was led to believe it would return individual items.

Suggestion: Update the sample to make it very clear what the dev has to do to use it.

Here’s the code to get this working…this included a lot of trial and error and debugging to figure out.

using System;
using System.Collections.Generic;
using System.IO;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Threading.Tasks;
using Azure;
using Azure.Cosmos;
using Azure.Cosmos.Serialization;
using DotNetEnv;
namespace cosmostest
{
    public class QueryStream
    {
        [JsonPropertyName("Documents")]
        public QueueMessage[] Documents { get; set; }
    }

    class Program
    {
        static async Task Main(string[] args)
        {
            Env.Load();

            CosmosClientOptions options = new CosmosClientOptions
            {
                SerializerOptions = new CosmosSerializationOptions { PropertyNamingPolicy = CosmosPropertyNamingPolicy.Default }
            };

            CosmosClient cosmosClient = new CosmosClient(
                        Environment.GetEnvironmentVariable("AZURE_COSMOS_ENDPOINT"),
                        Environment.GetEnvironmentVariable("AZURE_COSMOS_KEY"), options);

            CosmosContainer cosmosContainer = cosmosClient.GetDatabase(Environment.GetEnvironmentVariable("AZURE_COSMOS_DB")).GetContainer(Environment.GetEnvironmentVariable("AZURE_COSMOS_CONTAINER"));
            QueryDefinition queryDefinition = new QueryDefinition("SELECT * FROM c");
            List<QueueMessage> msgs = new List<QueueMessage>();

            await foreach (Response response in cosmosContainer.GetItemQueryStreamIterator(queryDefinition))
            {

                var queryStream = await JsonSerializer.DeserializeAsync<QueryStream>(response.ContentStream,
                    new JsonSerializerOptions() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase });

                msgs.AddRange(queryStream.Documents);
            }

        }
    }
}

azsdke2e

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:16 (15 by maintainers)

github_iconTop GitHub Comments

4reactions
SeanFeldmancommented, Sep 22, 2020

This API was really not intuitive. The GetItemQueryStreamIterator returning a document with the Documents property that’s the actual collection of the items is very confusing.

0reactions
ealsurcommented, Sep 22, 2020

@SeanFeldman That is part of the REST API contract. It is not part of the SDK definition nor a contract defined by the SDK, so there is nothing that can be done on the SDK to remove that property, because that is the server response as defined in https://docs.microsoft.com/en-us/rest/api/cosmos-db/query-documents#body-1.

If you are deserializing the Stream (this thread is for the Stream APIs) you could lookup that property to initialize the array/list that contains your results to avoid memory resizing if you wished, not really required, but it’s one usage I can think of.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Container.GetItemQueryStreamIterator Method
This method creates a query for items under a container in an Azure Cosmos database using a SQL statement with parameterized values. It...
Read more >
Exception when GetItemQueryIterator() can't find a ...
Does this really mean, that I need to add a try/catch, in case GetItemQueryIterator() can't find anything in Cosmos? Given that it is...
Read more >
Exploring the new .NET Cosmos DB SDK (v3)
So I took a look at the samples in the repo: https://github.com/Azure/azure-cosmos-dotnet-v3. It turns out we need a CosmosContainer object.
Read more >
C# (CSharp) ItemResponse Examples
C# (CSharp) ItemResponse - 60 examples found. These are the top rated real world C# (CSharp) examples of ItemResponse extracted from open source...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found