OData / AspNetCoreOData

ASP.NET Core OData: A server library built upon ODataLib and ASP.NET Core

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

$search does not work with aggregation and apply

AndriiLesiuk opened this issue · comments

OData 8.2.3

My query:

http://localhost:5066/odata/TableName?$apply=filter(frequency_name eq 'Annual' and concept_id in (1) and product_id in (112,207,138,77) and region_id in (164,339,262,263,255,257,338,219,302))/groupby((frequency_name), aggregate(frequency_id with sum as availableCounts))&$search=NavoiyAzot

image

My SearchBinder class:

public class SearchBinder : QueryBinder, ISearchBinder
{
    public Expression BindSearch<T>(SearchClause searchClause, QueryBinderContext context)
    {
        if (!typeof(T).IsAssignableFrom(context.ElementClrType))
        {
            return null;
        }

        SearchTermNode node = searchClause.Expression as SearchTermNode;

        return SearchBinderHelper.BindSearch<T>(node.Text);
    }

    public Expression BindSearch(SearchClause searchClause, QueryBinderContext context)
    {
        switch (System.Type.GetTypeCode(context.ElementClrType))
        {
            case TypeCode.Object:
                return BindSearch<TableName>(searchClause, context);

            default:
                return null;
        }
    }
}
 public static class SearchBinderHelper
 {
     public static Expression BindSearch<T>(string searchClause)
     {
         //SearchTermNode node = searchClause.Expression as SearchTermNode;

         var parameterExpression = Expression.Parameter(typeof(T), "record");
         var orExpressions = new List<Expression>();

         foreach (var propertyInfo in typeof(T).GetProperties())
         {
             if (propertyInfo.PropertyType == typeof(string))
             {
                 var memberExpression = Expression.Property(parameterExpression, propertyInfo);
                 var constantExpression = Expression.Constant(searchClause, typeof(string));
                 var callExpression = Expression.Call(memberExpression, "Contains", Type.EmptyTypes, constantExpression);
                 orExpressions.Add(callExpression);
             }
         }

         if (orExpressions.Count == 0)
         {
             return null;
         }

         var orExpression = orExpressions.Aggregate(Expression.OrElse);
         var predicate = Expression.Lambda<Func<T, bool>>(orExpression, parameterExpression);
         return predicate;
     }
 }

I will be grateful for any advice.

I also tried quick test implemenation:

 public Expression BindSearch(SearchClause searchClause, QueryBinderContext context)
 {
     SearchTermNode node = searchClause.Expression as SearchTermNode;
     if (node != null)
     {                 
             Expression<Func<TableName, bool>> exp = p => p.producer_name.Contains(node.Text);
             return exp; 
     }
     else
     {
         Expression exp = BindSingleValueNode(searchClause.Expression, context);

         LambdaExpression lambdaExp = Expression.Lambda(exp, context.CurrentParameter);

         return lambdaExp;
     }
 }

and it works fine without $apply,
with $apply:

image

In fact, it would be better to ask the question, is it even possible to force the catostomous SearchBinder to work with aggregation functions?

@AndriiLesiuk This is a known issue and we currently do not support $apply with $search. There is on-going work to support this.