我有一个有趣的挑战,我想有一个简单的答案。
我知道当你这样做的时候,嵌套过滤器是正确工作的:
var andFilter = FilterFactory.AndFilter(
FilterFactory.TermFilter("name.first", "shay1"),
FilterFactory.TermFilter("name.first", "shay4")
);我的基本服务应该允许调用者传入某种可枚举的要过滤的项目列表。
我基本上希望能够以编程方式实现这样的事情(过滤器被传递到方法中):
var andFilter = new FilterDescriptor();
foreach (var filter in filters)
{
andFilter = filter concatenated to andFilter
}换句话说,如果我传入一个由{ {"first.name","joe"},{"first.name","jim"},{"first.name","frank"}}组成的数组,我希望生成
var andFilter = FilterFactory.AndFilter(
FilterFactory.TermFilter("name.first", "joe"),
FilterFactory.TermFilter("name.first", "joe"),
FilterFactory.TermFilter("name.first", "frank")
);发布于 2012-12-03 04:53:49
使用基于lambda的DSL,您可以执行以下操作:
var termsFilters = from tp in termParameters
let field = ToCamelCaseNestedNames(tp.SearchField)
let terms = tp.SearchValues
select Filter.Terms(field, terms);
var prefixFilters = from tp in prefixParameters
let field = ToCamelCaseNestedNames(tp.SearchField)
let prefix = tp.SearchValues.FirstOrDefault().ToLowerInvariant()
select Filter.Prefix(field, prefix);
var search = client.Search(s => s
.From(0)
.Size(20)
.Filter(f => f.And(termsFilters.Concat(prefixFilters).ToArray()))
);我认为它读起来更好一些:)
嵌套现在还支持conditionless查询,因此如果任何tp.SearchValues为null、empty或all empty strings或tp.SearchField为null or empty,它将跳过术语/前缀查询。
不过,您可以很容易地恢复此行为:
var search = client.Search(s => s
.Strict()
.From(0)
.Size(20)
.Filter(f => f.And(termsFilters.Concat(prefixFilters).ToArray()))
);如果生成一个空查询,它将抛出一个DslException。
最后要注意的是,如果您可以强输入文档,那么client.Search()将返回一个QueryResult<dynamic>,因此也可以执行client.Search<MyDocument>()。
发布于 2014-03-04 23:02:11
Martijn的答案是最好的,但我想我应该添加一个我创建的例子,它对我来说是有效的,希望它能对其他人有所帮助。我构建了一个BaseQuery对象列表,然后使用.ToArray()方法将其放入查询中。
#region build query
var query = new List<BaseQuery>
{
Query<IAuthForReporting>.Range(r => r.OnField(f => f.AuthResult.AuthEventDate)
.From(authsByDateInput.StartDate.ToEPCISFormat())
.To(authsByDateInput.EndDate.ToEPCISFormat()))
};
if (authsByDateInput.AuthResult != AuthResultEnum.SuccessOrFailure)
{
var success = authsByDateInput.AuthResult == AuthResultEnum.Success;
query.Add(Query<IAuthForReporting>.Term(t => t.AuthResult.AuthenticationSuccessful, success));
}
if (authsByDateInput.ProductID != null)
{
query.Add(Query<IAuthForReporting>.Term(t => t.AuthResult.ProductID, authsByDateInput.ProductID.Value));
}
if (!authsByDateInput.CountryIDs.IsNullOrEmpty())
{
query.Add(Query<IAuthForReporting>.Terms(t => t.AuthResult.Address.CountryID, authsByDateInput.CountryIDs.Select(x=> x.Value.ToString()).ToArray()));
}
#endregion
var result =
ElasticClient.Search<IAuthForReporting>(s =>
s.Index(IndexName)
.Type(TypeName)
.Size(0)
.Query(q =>
q.Bool(b =>
b.Must(query.ToArray())
)
)
.FacetDateHistogram(t => t.OnField(f => f.AuthResult.AuthEventDate).Interval(DateInterval.Day))
);发布于 2012-11-19 22:38:26
在对这个主题进行了一些研究和开发之后,我能够解决这个问题,类似于下面的内容。我需要在和或支持上做一些额外的工作:
IList<IFilterBuilder> conditions = new List<IFilterBuilder>();
if (termParameters != null)
foreach (var termParameter in termParameters)
conditions.Add(FilterFactory.TermsFilter(ToCamelCaseNestedNames(termParameter.SearchField), termParameter.SearchValues));
if (prefixParameters != null)
foreach (var prefixParameter in prefixParameters)
conditions.Add(FilterFactory.PrefixFilter(ToCamelCaseNestedNames(prefixParameter.SearchField), prefixParameter.SearchValues.First().ToLowerInvariant()));
var filters = FilterFactory.AndFilter();
filters.Add(FilterFactory.AndFilter(conditions.ToArray()));
MatchAllQueryBuilder matchAllQueryBuilder = new MatchAllQueryBuilder();
FilteredQueryBuilder filteredQueryBuilder = new FilteredQueryBuilder(matchAllQueryBuilder, filters);
SearchBuilder searchBuilder = new SearchBuilder();
searchBuilder.Query(filteredQueryBuilder);
searchBuilder.Size(maxResults);https://stackoverflow.com/questions/13433981
复制相似问题