我有一个
dynamic
搜索描述符生成器。其中一个步骤是遍历范围过滤器列表并将其添加到搜索描述符中。
但是,我添加的任何范围查询都会覆盖以前的范围查询。
如何将范围查询附加到已添加的范围查询列表
public SearchDescriptor<dynamic> FilterSearch(SearchDescriptor<dynamic> searchDescriptor, List<FilterField> filters)
{
foreach (var filter in filters)
{
searchDescriptor = AddFilterToSearch(searchDescriptor, filter);
}
return searchDescriptor;
}
private static SearchDescriptor<dynamic> AddFilterToSearch(SearchDescriptor<dynamic> searchDescriptor, FilterField filter)
{
var range = new RangeQuery
{
Field = filter.Field
};
var term = new TermQuery
{
Field = filter.Field
};
string rangeValue = filter.Value == null ? null : JsonConvert.ToString(filter.Value);
// trim the quotes that JsonConvert wraps around the value for some reason
if (rangeValue != null && rangeValue.StartsWith("\"") && rangeValue.EndsWith("\""))
rangeValue = rangeValue.Substring(1, rangeValue.Length - 2);
switch (filter.Operator)
{
case Enums.ComparrisonOperator.LowerThan:
range.LowerThan = rangeValue;
break;
case Enums.ComparrisonOperator.LowerThanOrEqualTo:
range.LowerThanOrEqualTo = rangeValue;
break;
case Enums.ComparrisonOperator.Equals:
if (filter.Value != null && filter.Value is string)
filter.Value = filter.Value.ToString().ToLowerInvariant();
term.Value = filter.Value;
break;
case Enums.ComparrisonOperator.GreaterThan:
range.GreaterThan = rangeValue;
break;
case Enums.ComparrisonOperator.GreaterThanOrEqualTo:
range.GreaterThanOrEqualTo = rangeValue;
break;
}
switch (filter.Operator)
{
case Enums.ComparrisonOperator.LowerThan:
case Enums.ComparrisonOperator.LowerThanOrEqualTo:
case Enums.ComparrisonOperator.GreaterThan:
case Enums.ComparrisonOperator.GreaterThanOrEqualTo:
searchDescriptor = searchDescriptor.Query(range);
break;
case Enums.ComparrisonOperator.Equals:
searchDescriptor = searchDescriptor.Query(term);
break;
}
return searchDescriptor;
}
如果你正在使用 NEST,我认为你应该使用 QueryContainer。
var result = _Instance.Search<Record>(s => s
.Index("indexName")
.Type("type")
.Query(q =>
{
QueryContainer query = null;
QueryContainer filter1 = null;
QueryContainer filter2 = null;
QueryContainer filter3 = null;
query = q.QueryString(qs=>qs.OnFields(f => f.RecordValue).Query(term));
filter1 = q.Filter(ff => ff.Range(n => n.OnField(f => f.minAge).Lower(20));
filter2 = q.Filter(ff => ff.Range(n => n.OnField(f => f.minAge).Greater(20));
filter3 = q.Filter(ff => ff.Range(n => n.OnField(f => f.maxAge).Lower(60));
//You can put some conditions in here so you will
switch (filter.Operator)
{
case Enums.ComparrisonOperator.LowerThan:
return query && filter1;
break;
case Enums.ComparrisonOperator.GreaterThan:
return query && filter2;
break;
}
})
.Take(10)
);
或类似的东西......希望它有帮助!当然......这是针对 Elasticsearch < 2.0
可以用querycontainer添加,如下图:
var queryContainers = new List<QueryContainer>();
var descriptor = new QueryContainerDescriptor<ProcedureServiceRequest>();
queryContainers.Add(descriptor.DateRange(r => r.Field(f => f.Patient.Birthdate).GreaterThanOrEquals(startDate).LessThanOrEquals(endDate)));
var queryContainer = new QueryContainerDescriptor<ProcedureServiceRequest>().Match(m => m.Field(f => f.Specialty).Query("Ortho1"));
queryContainers.Add(queryContainer);
var queryContainer2 = new QueryContainerDescriptor<ProcedureServiceRequest>().Match(m => m.Field(f => f.PerformingPhysician.Id).Query("Practitioner2"));
queryContainers.Add(queryContainer2);
var filterQuery = new BoolQuery
{
Filter = queryContainers
};
var searchResponse = await elasticClient.SearchAsync<ProcedureServiceRequest>(s => s // Define the search query
.Index(indexName).Take(10000)
.Query(q => q
.Bool(b => b
.Filter(filterQuery
)
.Must(m => m
.QueryString(qs => qs
.Fields(fs => fs.Field("*"))
.Query(query))))).Sort(srt => srt.Field(f=> {
f.Order(Nest.SortOrder.Ascending);
switch (sortfield)
{
case "Birthdate":
f.Field(ff => ff.Patient.Birthdate);
break;
default:
f.Field(ff => ff.Start);
f.Descending();
break;
}
return f;
})));
return searchResponse.Documents.ToList();