|
class CompositeFilterMapper<T> |
|
{ |
|
private readonly CompositeFilterDescriptor _compositeFilterDescriptor;= |
|
|
|
public CompositeFilterMapper(CompositeFilterDescriptor compositeFilterDescriptor) |
|
{ |
|
_compositeFilterDescriptor = compositeFilterDescriptor; |
|
} |
|
|
|
public QueryContainer GetQueryContainer(QueryContainerDescriptor<ElasticDataUpload<T>> query) |
|
{ |
|
return ApplyQuery(new[] {_compositeFilterDescriptor}, _compositeFilterDescriptor.Logic, query); |
|
} |
|
|
|
private QueryContainerDescriptor<T> ApplyQuery( |
|
IEnumerable<CompositeFilterDescriptor> filterFilters, string filterOperator, |
|
QueryContainerDescriptor<T> query) |
|
{ |
|
List<QueryContainerDescriptor<T>> innerQueries = |
|
new List<QueryContainerDescriptor<T>>(); |
|
|
|
foreach (var filter in filterFilters) |
|
{ |
|
if (filter.Filters != null && filter.Filters.Any()) |
|
{ |
|
innerQueries.Add(ApplyQuery(filter.Filters, filter.Logic, query)); |
|
} |
|
else |
|
{ |
|
innerQueries.Add((QueryContainerDescriptor<T>)CreateQuery(filter.Field, filter.Operator, filter.IgnoreCase, filter.Logic, filter.Value, query)); |
|
} |
|
} |
|
|
|
if (filterOperator == "and") |
|
{ |
|
return (QueryContainerDescriptor<T>)query.Bool(b => b.Must(innerQueries.Cast<QueryContainer>().ToArray())); |
|
} |
|
else if (filterOperator == "or") |
|
{ |
|
return (QueryContainerDescriptor<T>) query.Bool(b => b.Should(innerQueries.Cast<QueryContainer>().ToArray())); |
|
} |
|
else |
|
{ |
|
throw new ArgumentOutOfRangeException(); |
|
} |
|
} |
|
|
|
private QueryContainer CreateQuery(string filterField, |
|
string filterOperator,bool? filterIgnoreCase, string filterLogic, object value, |
|
QueryContainerDescriptor<T> query) |
|
{ |
|
var type = MapToType(filterField); |
|
var propertyExpression = MapToProperty(filterField); |
|
|
|
return CreateQuery(query,type, propertyExpression, filterOperator, value); |
|
} |
|
|
|
private QueryContainer CreateQuery(QueryContainerDescriptor<T> query, |
|
Type fieldType, Expression<Func<T, object>> propertyExpression, |
|
string filterOperator, object value) |
|
{ |
|
if (fieldType == typeof(String)) |
|
{ |
|
return CreateStringFilter(query,propertyExpression, filterOperator, value); |
|
} |
|
else if (fieldType == typeof(DateTime)) |
|
{ |
|
return CreateDateTimeFilter(query, propertyExpression, filterOperator, value); |
|
} |
|
else |
|
{ |
|
throw new ArgumentOutOfRangeException(); |
|
} |
|
} |
|
|
|
private QueryContainer CreateDateTimeFilter(QueryContainerDescriptor<ElasticDataUpload<SystemLog>> query, |
|
Expression<Func<ElasticDataUpload<SystemLog>, object>> propertyExpression, string filterOperator, |
|
object value) |
|
{ |
|
switch (filterOperator) |
|
{ |
|
case "eq": |
|
return query.DateRange(d => d.Field(propertyExpression) |
|
.GreaterThanOrEquals(DateMath.Anchored((DateTime)value)) |
|
.LessThanOrEquals(DateMath.Anchored((DateTime)value))); |
|
case "neq": |
|
return query.DateRange(d => d.Field(propertyExpression) |
|
.GreaterThanOrEquals(DateMath.Anchored((DateTime)value)) |
|
.LessThanOrEquals(DateMath.Anchored((DateTime)value))); |
|
case "isnull": |
|
throw new ArgumentException("Unable to apply less than to date and time queries"); |
|
case "isnotnull": |
|
throw new ArgumentException("Unable to apply less than to date and time queries"); |
|
case "lt": |
|
return query.DateRange(d => d.Field(propertyExpression).LessThan(DateMath.Anchored((DateTime)value))); |
|
case "lte": |
|
return query.DateRange(d => d.Field(propertyExpression).LessThanOrEquals(DateMath.Anchored((DateTime)value))); |
|
case "gt": |
|
return query.DateRange(d => d.Field(propertyExpression).GreaterThan(DateMath.Anchored((DateTime)value))); |
|
case "gte": |
|
return query.DateRange(d => d.Field(propertyExpression).GreaterThanOrEquals(DateMath.Anchored((DateTime)value))); |
|
case "startswith": |
|
throw new ArgumentException("Unable to apply less than to date and time queries"); |
|
case "endswith": |
|
throw new ArgumentException("Unable to apply less than to date and time queries"); |
|
case "contains": |
|
throw new ArgumentException("Unable to apply less than to date and time queries"); |
|
case "doesnotcontain": |
|
throw new ArgumentException("Unable to apply less than to date and time queries"); |
|
case "isempty": |
|
throw new ArgumentException("Unable to apply less than to date and time queries"); |
|
case "isnotempty": |
|
throw new ArgumentException("Unable to apply less than to date and time queries"); |
|
default: |
|
throw new ArgumentOutOfRangeException(); |
|
} |
|
} |
|
|
|
private QueryContainer CreateStringFilter(QueryContainerDescriptor<T> query, |
|
Expression<Func<T, object>> propertyExpression, |
|
string filterOperator, object value) |
|
{ |
|
switch (filterOperator) |
|
{ |
|
case "eq": |
|
return query.QueryString(qs => qs.Fields(fs => fs.Field(propertyExpression)).Query((string)value)); |
|
case "neq": |
|
return query.Bool(b => b.MustNot(x => x.QueryString(qs => qs.Fields(fs => fs.Field(propertyExpression)).Query((string)value)))); |
|
case "isnull": |
|
return query.QueryString(qs => qs.Fields(fs => fs.Field(propertyExpression)).Query(null)); |
|
case "isnotnull": |
|
return query.Bool(b => b.MustNot(x => x.QueryString(qs => qs.Fields(fs => fs.Field(propertyExpression)).Query(null)))); |
|
case "lt": |
|
throw new ArgumentException("Unable to apply less than to string queries"); |
|
case "lte": |
|
throw new ArgumentException("Unable to apply less than equal to string queries"); |
|
case "gt": |
|
throw new ArgumentException("Unable to apply greater than to string queries"); |
|
case "gte": |
|
throw new ArgumentException("Unable to apply greater than equal to string queries"); |
|
case "startswith": |
|
return query.Bool(b => b.Should(x => x.Term(propertyExpression, value))); |
|
case "endswith": |
|
return query.Bool(b => b.Should(x => x.Term(propertyExpression, value))); |
|
case "contains": |
|
return query.Match(qs => qs.Field(propertyExpression).Query((string)value).Operator(Operator.And)); |
|
case "doesnotcontain": |
|
return query.Bool(b => b.MustNot(x => x.Match(qs => qs.Field(propertyExpression).Query((string)value).Operator(Operator.And)))); |
|
case "isempty": |
|
return query.QueryString(qs => qs.Fields(fs => fs.Field(propertyExpression)).Query("")); |
|
case "isnotempty": |
|
return query.Bool(b => b.MustNot(x => x.QueryString(qs => qs.Fields(fs => fs.Field(propertyExpression)).Query("")))); |
|
default: |
|
throw new ArgumentOutOfRangeException(); |
|
} |
|
} |
|
|
|
private System.Linq.Expressions.Expression<Func<T, object>> MapToProperty(string fieldName) |
|
{ |
|
switch (fieldName) |
|
{ |
|
//return expressions from property names |
|
default: |
|
throw new ArgumentOutOfRangeException(); |
|
} |
|
} |
|
|
|
private Type MapToType(string fieldName) |
|
{ |
|
switch (fieldName) |
|
{ |
|
// Map field name to type |
|
// return typeof(String); |
|
default: |
|
throw new ArgumentOutOfRangeException(); |
|
} |
|
} |
|
} |