首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在嵌套中“动态”创建过滤器

在嵌套中“动态”创建过滤器
EN

Stack Overflow用户
提问于 2012-11-18 03:25:33
回答 3查看 5.5K关注 0票数 6

我有一个有趣的挑战,我想有一个简单的答案。

我知道当你这样做的时候,嵌套过滤器是正确工作的:

代码语言:javascript
复制
var andFilter = FilterFactory.AndFilter(
                    FilterFactory.TermFilter("name.first", "shay1"),
                    FilterFactory.TermFilter("name.first", "shay4")
                );

我的基本服务应该允许调用者传入某种可枚举的要过滤的项目列表。

我基本上希望能够以编程方式实现这样的事情(过滤器被传递到方法中):

代码语言:javascript
复制
var andFilter = new FilterDescriptor();
foreach (var filter in filters) 
{
     andFilter = filter concatenated to andFilter
}

换句话说,如果我传入一个由{ {"first.name","joe"},{"first.name","jim"},{"first.name","frank"}}组成的数组,我希望生成

代码语言:javascript
复制
var andFilter = FilterFactory.AndFilter(
                    FilterFactory.TermFilter("name.first", "joe"), 
                    FilterFactory.TermFilter("name.first", "joe"),
                    FilterFactory.TermFilter("name.first", "frank")
                );
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2012-12-03 04:53:49

使用基于lambda的DSL,您可以执行以下操作:

代码语言:javascript
复制
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.SearchValuesnullemptyall empty stringstp.SearchFieldnull or empty,它将跳过术语/前缀查询。

不过,您可以很容易地恢复此行为:

代码语言:javascript
复制
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>()

票数 9
EN

Stack Overflow用户

发布于 2014-03-04 23:02:11

Martijn的答案是最好的,但我想我应该添加一个我创建的例子,它对我来说是有效的,希望它能对其他人有所帮助。我构建了一个BaseQuery对象列表,然后使用.ToArray()方法将其放入查询中。

代码语言:javascript
复制
    #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))
                );
票数 1
EN

Stack Overflow用户

发布于 2012-11-19 22:38:26

在对这个主题进行了一些研究和开发之后,我能够解决这个问题,类似于下面的内容。我需要在和或支持上做一些额外的工作:

代码语言:javascript
复制
        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);
票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/13433981

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档