How to build dynamic queries for MongoDB in c# using both & and | operators

1k Views Asked by At

So i have a list of key value pairs witch the key is a string and the value is an array of strings as follows:

{
    "filters": [
        {"key": "team", "value": ["3","4","7"]},
        {"key": "placement_type", "value": ["facility"]}
        //{"key": "date", "value": ["2021-01-01"]}
        //{"key": "policy", "value": ["something"]} Number of filters may vary
    ]
}

This list of "filters" can have multiple Key Value pairs depending on the number of filters the user has chosen.

So what i need is to dynamically create is the following query:

(builder.Eq("team", "3") | builder.Eq("team", "4") | builder.Eq("team", "7")) & builder.Eq("placement_type", "Facility");

And this is my attempt:

var builder = Builders<ReportDocument>.Filter;

// IF I USE THIS QUERY IT WORKS AS I EXPECT
var hardCodedQuery = (builder.Eq("team", "3") | builder.Eq("team", "4") | builder.Eq("team", "7")) & builder.Eq("placement_type", "Facility");

var dynamicQuery = builder.Empty;
var orFilters = builder.Empty;

foreach (var filter in request.Filters)
{
  if (filter.Value.Length > 1)
  {
     for (int i = 0; i < filter.Value.Length; i++)
     {
        if (i == 0)
        {
          orFilters = builder.Eq(filter.Key, filter.Value[i]); //Had to do this since i have to initiate the variable as builder.Empty and it was adding and EmptyFilterDefinition
        }
        else
        {
          orFilters &= builder.Eq(filter.Key, filter.Value[i]);
        }
      }
      dynamicQuery = builder.Or(orFilters);
   }
   else
   {
      dynamicQuery &= builder.Eq(filter.Key, filter.Value);
   }
}
return await _reportsCollection.Find(dynamicQuery).ToListAsync();

But once i insert the second filter in the variable "orFilters" with the operator "&=" e becomes a MongoDB.Driver.AndFilterDefinition instead of MongoDB.Driver.OrFilterDefinition

So if anyone has a good way to do this please share it guys. I saw a lot of questions similar like mine in stackoverflow but all refer do doing dynamic filters using just the & (And) operator. But since i have a list of strings as value i need to use the | (Or) operator as well.

Thanks

1

There are 1 best solutions below

0
On

Your first compound assignment doesn't match your expected query, in your example you use OR but in your code you are using AND assignment

....
if (filter.Value.Length > 1)
  {
     for (int i = 0; i < filter.Value.Length; i++)
     {
        if (i == 0)
        {
          orFilters = builder.Eq(filter.Key, filter.Value[i]); //Had to do this since i have to initiate the variable as builder.Empty and it was adding and EmptyFilterDefinition
        }
        else
        {
          // this line was changed 
          orFilters |= builder.Eq(filter.Key, filter.Value[i]);
        }
      }
      //also when this line run, you are resetting your filter so pay attention to it, should change
      dynamicQuery = builder.Or(orFilters);
   }
   .....