Home > Enterprise >  How to override the filtering link query generated by HotChocolate?
How to override the filtering link query generated by HotChocolate?

Time:12-20

I have a case where I need to send tens of thousands of ids to the graphql server in the filtering query.

the query now generated by the HT is something like this:

_dbContext.
  Forms
  .Where(c=>staticLiistOfIds.Contains(c.Id))
  .Select(c=>new {C.Name,C.Age});

I have two problems with this: 1-slow performance 2-SQL Server Limit I guess is around 32K

I have found a Nuget library to convert this static list to a temp table,so now I want to override the HT middle to rewrite the above query generated to the following :

_dbContext.
  Forms
  .Where(c=>_dbContext..AsQueryableValues(staticLiistOfIds).Contains(c.Id))
  .Select(c=>new {C.Name,C.Age});

this will create a temp table for this static list of ids so I will be able to solve the above two problems that I have.

Thank you very much for your answer.

CodePudding user response:

So since i didn't get answers, I had to ask from the Slack of HotChocolate's Team and hopefully, they provided me with the documentation extending-filtering/extending-iqueryable:

in case the link was broken, here is

Extending IQueryable The default filtering implementation uses IQueryable under the hood. You can customize the translation of queries by registering handlers on the QueryableFilterProvider.

The following example creates a StringOperationHandler that supports case-insensitive filtering:

// The QueryableStringOperationHandler already has an implemenation of CanHandle
// It checks if the field is declared in a string operation type and also checks if
// the operation of this field uses the `Operation` specified in the override property further
// below
public class QueryableStringInvariantEqualsHandler : QueryableStringOperationHandler
{
    // For creating a expression tree we need the `MethodInfo` of the `ToLower` method of string
    private static readonly MethodInfo _toLower = typeof(string)
        .GetMethods()
        .Single(
            x => x.Name == nameof(string.ToLower) &&
            x.GetParameters().Length == 0);

    // This is used to match the handler to all `eq` fields
    protected override int Operation => DefaultFilterOperations.Equals;

    public override Expression HandleOperation(
        QueryableFilterContext context,
        IFilterOperationField field,
        IValueNode value,
        object parsedValue)
    {
        // We get the instance of the context. This is the expression path to the propert
        // e.g. ~> y.Street
        Expression property = context.GetInstance();

        // the parsed value is what was specified in the query
        // e.g. ~> eq: "221B Baker Street"
        if (parsedValue is string str)
        {
            // Creates and returnes the operation
            // e.g. ~> y.Street.ToLower() == "221b baker street"
            return Expression.Equal(
                Expression.Call(property, _toLower),
                Expression.Constant(str.ToLower()));
        }

        // Something went wrong            
  • Related