3
votes

I was trying to find examples about the best approach to model / query complex data types on Azure Search. I could only found two approaches to model described on the following link:

https://docs.microsoft.com/en-us/azure/search/search-howto-complex-data-types

But no samples on how to query for a particular property from the JSON. It seems that this feature is on preview mode at this stage:

https://feedback.azure.com/forums/263029-azure-search/suggestions/6670910-modelling-complex-types-in-indexes

Let's say I have a complex type that I would like to store into one field on Azure Search:

{
   "name": "Thiago",
   "email": "[email protected]",
   "subscription": {
      "plan": "A",
      "billType": "month", 
      "tags": ["azure", "mvp", "search"]
   }
}

Let's say I want to filter for documents that contains the tag "azure". Or for those that have the billType "month"

1
Can you elaborate on what you mean by "query for a particular property from the JSON"? Do you mean filtering based on the value of a property, or projecting the results to only that property...?Bruce Johnston
That example isn't valid JSON. The inner object must be assigned to some named property of the outer object.Bruce Johnston
sorry @BruceJohnston I was trying to edit as fast as I could, and didn't realized I've forgot one property. Now it's a valid one.Thiago Custodio
I'll edit my answer to specifically address this example.Bruce Johnston

1 Answers

2
votes

When emulating complex types using the approach mentioned in that article, you can filter the same way you would with "flat types". However, this brings some limitations.   One of the limitations of emulating complex types with collections is that you can’t perform filters on "sub-documents" easily. Taking the example from the article, imagine you have locationsId and locationsDescription fields. If you perform a filter like this:

$filter=locationsId/any(id: id eq '4') and locationsDescription/any(d: d eq 'Home office')

  You may get more results than you wanted. For example, you may get documents that have a locationsId of 3 with the description "Home office", or a locationsId of 4 with a different locationsDescription. This is because the two clauses above must use separate lambda expressions, so the comparisons are not done to the same logical 'sub-document'. One workaround mentioned in the article is to index combinations of values together. If you had a locationsCombined field, you could filter it like this (assuming you indexed the values using | as a separator):

$filter=locationsCombined/any(c: c eq '4|Home office')

This still has some limitations on what you can express inside the lambda though.

Fortunately we are working on native support for Complex Types, so soon such workarounds will not be necessary.

Edit

To address your specific example, assuming you're modeling your data in a "flattened" schema per the article, you can filter on tags like this:

$filter=subscriptionTags/any(t: t eq 'azure')

And you can filter on billType like this:

$filter=subscriptionBillType eq 'month'

This "flattening" won't be necessary once the Complex Types feature is generally available.