Skip to main content

Querying for items in an Array in CosmosDB

If you have spent any time looking at the documentation for Microsoft CosmosDB / DocumentDB, you will see a lot of examples where the data model has a property named "Tags" that is a list of strings.  But you don't see many times they query on something in that Tag property...  One example I saw a query on Tags[0] = "some value" I don't know how often I will need that, but you know, good to know you can do it.

After looking through the SQL syntax reference.  The 2 ways I most likely query the Tags would be to use a join on the Tags property or use the ARRAY_CONTAINS function.

Side note; the performance of the two methods are basically identical, leading me to believe the query optimizer generates the same instruction sets for both. So unless you have an array of complex objects, just use ARRAY_CONTAINS.

Cool, we know how to query for documents that have our tag on them now... One small problem, when you load a million, or even a hundred thousand documents, your queries start taking seconds to complete, and 10's of thousands of request units.  That's not going to work.

It seams the default indexing policy doesn't index the values in an array, and then that means that CosmosDB is having to open every document that matches your base query.  Thankfully there is a way around this.  If you add a path of "/tags/[]/?" you will find the same query returns in a fraction of a second, and less then 100 RUs.

Sample Index Policy:
{
  "indexingMode": "lazy",
  "automatic": true,
  "includedPaths": [
    {
      "path": "/*",
      "indexes": [
        {
          "kind": "Hash",
          "dataType": "String",
          "precision": -1
        },
        {
          "kind": "Range",
          "dataType": "Number",
          "precision": -1
        }
      ]
    },
    {
      "path": "/tags/[]/?",
      "indexes": [
        {
          "kind": "Hash",
          "dataType": "String",
          "precision": -1
        },
        {
          "kind": "Range",
          "dataType": "Number",
          "precision": -1
        }
      ]
    }
  ],
  "excludedPaths": []
}

Popular posts from this blog

Getting Azure AD JWT via Postman

In my last post, I reviewed how to use Azure AD for service to service authentication.  But sometimes, you may want to test your API directly.  So let's review how to get the token via Postman. We are going to be using the OAuth2 endpoint, and going for a "client_credentials" grant type.  So you are going to need to know a few things from your Azure portal. Application Id : This is used for the Client Id. Application key : This is used for the Client Secret.  You have to generate this from the portal, and it will only give it back to you once.  If you lose it, you will have to generate a new one. Application ID URI : we will use this as our resource.  This is the Application ID URI for the app we are going to be calling, not the one we are login on as.  (See What is the Resource in Azure AD for more information) (optional) Tenant Id : This is used to figure out where the Token Endpoint is.  The new Azure portal calls this a Directory ...

What is the Resource in Azure AD OAuth2

In my post about getting the Azure AD JWT via Postman , we kind of skipped over the part on what the resource is when requesting a token.  Basically, its the Application Id URI of the app you will be calling, not the app you are login in as.  Let's talk through a scenario, using the https://github.com/Azure-Samples/active-directory-dotnet-daemon sample from my post on Service to Service auth. You would create two applications in Azure AD, and they don't even need to be in the same AD (we will cover that at a later date).  The service that is going to consume the API (TodoListDaemon) is the one that would be using the method I described to get a bearer token, and it would have its own Application as we would use its App ID for the Client Id.  Then the service hosting the API (TodoListService) would also have its own Application, but we don't need to generate an Application Key, as we are not logging on as this application.  But in TodoListService we would p...