Search code examples
c++odataazure-cognitive-search

Check if a flag is set on an enum field in Azure Cognitive Search using OData Query Syntax


I have to find a way to query (am using Azure search) whether or not a field has a set of flags set without using bitwise and. The reason for the limitation is that Azure Cognitive Search uses OData for querying, which does not support any bitwise operations.

Say we have an enum like so:

public enum PreferredColors
{
     red = 1,
     blue = 2,
     green = 4,
     yellow = 8
}

Now say I have a user who prefers yellow, blue, and red. I'm want to check for users that prefer yellow and red. Normally you would do that like so:

PreferredColors preference = PreferredColors.red | PreferredColors.yellow
bool res = (preference & user.ColorPreferences) == preference

Where res is the result we're looking for. This check has to be part of the query (for paging reasons). Is there any other way I can perform this check that avoids using bitwise &?


Solution

  • Azure Cognitive Search doesn't support OData enums, so you'll have to model this scenario with a different data type than Edm.Int32. Depending on how you want to model things in your application, you could use either Collection(Edm.Int32) or maybe Collection(Edm.String). Let's use a string collection for these examples just for the sake of clarity.

    Another thing you can't do in Azure Cognitive Search is compare one field of an index to another field, so I'm going to assume that the desired color preferences are known to the application code and can be injected into the query string that you're going to send to Azure Cognitive Search. The scenario is that for any given document in the search index, you want to check whether all of the preferred colors given to the application are present in the colors for that document.

    Here's how you would express this query using a string collection field if the color preferences to search for are 'red' and 'green':

    $filter=preferences/any(p: p eq 'red') and preferences/any(p: p eq 'green')
    

    If you have a document where the preferences field contains ["green", "yellow", "red"] for example, then the above query will match.