alirezanet/Gridify

Filtering based on IDictionary values

alirezanet opened this issue · 0 comments

Discussed in #164

Originally posted by ameckl May 12, 2024

I'm currently using Sieve's custom filter methods to achieve this functionality, but planning to migrate to Gridify.

Hello, I'm using MongoDb as database, where I have a couple of entities with sub-documents storing additional information, represented as IDictionary<string, string>.

e.g.

public class ExampleEntity
{
   public IDictionary<string, string> Data { get; init; }
}

Is it possible to achieve filtering based on the values of this Dictionary?

The keys of these dictionaries are not known, so I cannot just AddMap("data.key1"), AddMap("data.key2").

One solution would be to implement a custom operator, then cast the value to an IDictionary, but that seems like an overkill (and then I need to implement other custom operators for NotEquals, Contains, etc).

It would be great to have support on sub-documents, just like there is support for sub-collections. Maybe something like:

var gq = new GridifyQuery { Filter = "prop{subKey} = John"};

var gm = new GridifyMapper<TargetType>()
      .AddMap("prop", (x , prop) => x.Data[prop]);

// would generate an IQueryable like

IQueryable<TargetType>().Where(e => e.Data["subKey"] == "John");

For reference, my current approach (using Sieve) looks like this:

public IQueryable<ExampleEntity> DataValue(IQueryable<ExampleEntity> source, string op, string[] values)
    {
        if (values.Length != 2)
        {
            return source;
        }

        string key = values.First();
        string value = values.Last();

        if (op == "==")
        {
            source = source.Where(d => d.Data[key] == value);
        }
        // ... the rest of operators   

        return source;
    }

// where
IQueryable<ExampleEntity> source = MongoCollection.AsQueryable();
// then GET /api/example?filters="DataValue==key1|value1"

Or maybe is it planned to support custom filter methods (like Sieve), where we have access to the IQueryable that is being filtered? (that's how we achieved search in our past projects)

e.g.

// really basic example
public IQueryable<ExampleEntity> Search(IQueryable<ExampleEntity> source, string op, string[] values)
    {
        
        string value = values.First();
        // here we have the possibility to access the Queryable and to call database engine specific clauses like a Mongo text search.
        source = source.Where(d => d.Name.Contains(value) || d.Description.Contains(value))

        return source;
    }

// then GET /api/example?filters="search==searchString"
```</div>