Created
August 19, 2018 23:40
-
-
Save QiMata/81e08d880401e0111b2c62415ed7e1cd to your computer and use it in GitHub Desktop.
The ElasticSearch query mapper
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment