"动态地"在NEST中创建过滤器

Rog*_*oys 5 c# elasticsearch nest

我有一个有趣的挑战,我认为有一个简单的答案.

我知道NEST过滤器在语法上你可以正常工作:

var andFilter = FilterFactory.AndFilter(
                    FilterFactory.TermFilter("name.first", "shay1"),
                    FilterFactory.TermFilter("name.first", "shay4")
                );
Run Code Online (Sandbox Code Playgroud)

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

我基本上希望能够以编程方式实现这样的东西(过滤器传递给方法):

var andFilter = new FilterDescriptor();
foreach (var filter in filters) 
{
     andFilter = filter concatenated to andFilter
}
Run Code Online (Sandbox Code Playgroud)

换句话说,如果我传入了{{"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")
                );
Run Code Online (Sandbox Code Playgroud)

Mar*_*man 9

使用基于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()))
);
Run Code Online (Sandbox Code Playgroud)

我觉得它读得更好:)

鸟巢现在还支持conditionless查询,因此,如果任何tp.SearchValuesnull,empty或者all empty strings或者tp.SearchFieldnull or empty它会跳过该条款/前缀查询.

您可以轻松地还原此行为:

var search = client.Search(s => s
    .Strict()
    .From(0)
    .Size(20)
    .Filter(f => f.And(termsFilters.Concat(prefixFilters).ToArray()))
);
Run Code Online (Sandbox Code Playgroud)

DslException如果生成一个空查询,将抛出一个.

如果您可以强力键入文档,那么最后一个注释client.Search()将返回a QueryResult<dynamic>,因此可以执行操作client.Search<MyDocument>().