$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
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:
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.