5

我想用 NEST 附加多个布尔过滤器,但我不能(实际上)在一个语句中做到这一点,因为我想根据不同的条件构建一组布尔过滤器。

像这样的伪代码:

// Append a filter
searchDescriptor.Filter(f => f.Bool(b => b.Must(m => m.Term(i => i.SomeProperty, "SomeValue"))));

if (UserId.HasValue)
{
   // Optionally append another filter (AND condition with the first filter)
   searchDescriptor.Filter(f => f.Bool(b => b.Must(m => m.Term(i => i.AnotherProperty, "MyOtherValue"))));
}

var result = Client.Search(searchDescriptor);

现在看来,当附加第二个可选过滤器时,它基本上取代了第一个过滤器。

我确定我在语法上遗漏了一些东西,但我无法弄清楚,并且 NEST 文档在过滤器 DSL 上有点薄。:)

4

2 回答 2

12

关于编写查询的部分也几乎适用于过滤器: https ://www.elastic.co/guide/en/elasticsearch/client/net-api/current/writing-queries.html

您最终得到的解决方案并不理想,因为您将bool过滤器包装在and具有非常不同缓存机制的过滤器中(并且过滤器不使用缓存的位集,因此在大多数情况下,性能比常规布尔过滤器差)。

强烈推荐阅读http://www.elastic.co/blog/all-about-elasticsearch-filter-bitsets/因为它很好地解释了 and/or/not 过滤器与 bool 过滤器之间的区别。

您实际上可以像这样重写它:

Client.Search(s=>s
    .Filter(f=> { 
        BaseFilter ff = f.Term(i => i.MyProperty, "SomeValue");
        if (UserId.HasValue)
            ff &= f.Term(i => i.AnotherProperty, "AnotherValue");
        return ff;
    })
);

如果第二个词是使用 UserId 进行搜索,您可以利用 NEST 的conditionless queries

Client.Search(s=>s
    .Filter(f=> 
        f.Term(i => i.MyProperty, "SomeValue") 
        && f.Term(i => i.AnotherProperty, UserId)
    )
);

如果UserId为空,则不会生成术语查询作为查询的一部分,在这种情况下,嵌套甚至不会将单个剩余术语包装在布尔过滤器中,而是将其作为普通术语过滤器发送。

于 2013-11-03T10:42:07.130 回答
1

啊,这样的事情似乎有效:

        var filters = new List<BaseFilter>();

        // Required filter
        filters.Add(new FilterDescriptor<MyType>().Bool(b => b.Must(m => m.Term(i => i.MyProperty, "SomeValue"))));

        if (UserId.HasValue)
        {
            filters.Add(new FilterDescriptor<MyType>().Bool(b => b.Must(m => m.Term(i => i.AnotherProperty, "AnotherValue"))));
        }

        // Filter with AND operator
        searchDescriptor.Filter(f => f.And(filters.ToArray()));

        var result = Client.Search(searchDescriptor);
于 2013-10-28T17:13:43.480 回答