Skip to content

Instantly share code, notes, and snippets.

@QiMata
Created August 19, 2018 23:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save QiMata/81e08d880401e0111b2c62415ed7e1cd to your computer and use it in GitHub Desktop.
Save QiMata/81e08d880401e0111b2c62415ed7e1cd to your computer and use it in GitHub Desktop.
The ElasticSearch query mapper
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