java ElasticSearch - 使用 FilterBuilders

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16487548/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 23:06:29  来源:igfitidea点击:

ElasticSearch - Using FilterBuilders

javaelasticsearchcouchbase

提问by aces.

I am new to ElasticSearch and Couchbase. I am building a sample Java application to learn more about ElasticSearch and Couchbase.

我是 ElasticSearch 和 Couchbase 的新手。我正在构建一个示例 Java 应用程序以了解有关 ElasticSearch 和 Couchbase 的更多信息。

Reading the ElasticSearch Java API, Filters are better used in cases where sort on score is not necessary and for caching. I still haven't figured out how to use FilterBuilders and have following questions:

阅读ElasticSearch Java API,在不需要按分数排序和缓存的情况下,最好使用过滤器。我仍然没有弄清楚如何使用 FilterBuilders 并有以下问题:

  • Can FilterBuildersbe used alone to search?
  • Or Do they always have to be used with a Query? ( If true, can someone please list an example? )
  • Going through a documentation, if I want to perform a search based on field values and want to use FilterBuilders, how can I accomplish that? (using AndFilterBuilderor TermFilterBuilderor InFilterBuilder? I am not clear about the differences between them.)
  • 可以FilterBuilders单独使用搜索吗?
  • 或者他们总是必须与 a 一起使用Query吗?(如果是真的,有人可以举个例子吗?)
  • 通过文档,如果我想根据字段值执行搜索并想使用 FilterBuilders,我该如何完成?(使用AndFilterBuilderorTermFilterBuilderInFilterBuilder?我不清楚它们之间的区别。)

For the 3rd question, I actually tested it with search using queries and using filters as shown below. I got empty result (no rows) when I tried search using FilterBuilders. I am not sure what am I doing wrong.

对于第三个问题,我实际上通过使用查询和过滤器的搜索对其进行了测试,如下所示。当我尝试使用FilterBuilders. 我不确定我做错了什么。

Any examples will be helpful. I have had a tough time going through documentation which I found sparse and even searching led to various unreliable user forums.

任何示例都会有所帮助。我在浏览文档时遇到了困难,我发现这些文档很少,甚至搜索导致了各种不可靠的用户论坛。

private void processQuery() {
        SearchRequestBuilder srb = getSearchRequestBuilder(BUCKET);
        QueryBuilder qb = QueryBuilders.fieldQuery("doc.address.state", "TX");
        srb.setQuery(qb);

        SearchResponse resp = srb.execute().actionGet();
        System.out.println("response :" + resp);
    }

private void searchWithFilters(){
        SearchRequestBuilder srb = getSearchRequestBuilder(BUCKET);
        srb.setFilter(FilterBuilders.termFilter("doc.address.state", "tx"));
        //AndFilterBuilder andFb = FilterBuilders.andFilter();
        //andFb.add(FilterBuilders.termFilter("doc.address.state", "TX")); 
        //srb.setFilter(andFb);
        SearchResponse resp = srb.execute().actionGet();
        System.out.println("response :" + resp);
    }

--UPDATE--

--更新--

As suggested in the answer, changing to lowercase "tx" works. With this question resolved. I still have following questions:

正如答案中所建议的,更改为小写的“tx”有效。有了这个问题就解决了。我还有以下问题:

  • In what scenario(s), are filters used with query? What purpose will this serve?
  • Difference between InFilter, TermFilterand MatchAllFilter. Any illustration will help.
  • 在什么情况下,过滤器与查询一起使用?这将服务于什么目的?
  • InFilterTermFilter和之间的区别MatchAllFilter。任何插图都会有所帮助。

回答by javanna

Right, you should use filters to exclude documents from being even considered when executing the query. Filters are faster since they don't involve any scoring, and cacheable as well.

是的,您应该使用过滤器来排除在执行查询时被考虑的文档。过滤器速度更快,因为它们不涉及任何评分,并且也可缓存。

That said, it's pretty obvious that you have to use a filter with the search api, which does execute a query and accepts an optional filter. If you only have a filter you can just use the match_allquery together with your filter. A filter can be a simple one, or a compund one in order to combine multiple filters together.

也就是说,很明显您必须在搜索 api 中使用过滤器,它会执行查询并接受可选过滤器。如果您只有一个过滤器,您可以将match_all查询与您的过滤器一起使用。过滤器可以是简单的过滤器,也可以是复合过滤器,以便将多个过滤器组合在一起。

Regarding the Java API, the names used are the names of the filters available, no big difference. Have a look at this search examplefor instance. In your code I don't see where you do setFilteron your SearchRequestBuilderobject. You don't seem to need the and filter either, since you are using a single filter. Furthermore, it might be that you are indexing using the default mappings, thus the term "TX" is lowercased. That's why when you search using the term filter you don't find any match. Try searching for "tx" lowercased.

关于Java API,使用的名称是可用过滤器的名称,没有太大区别。例如,看看这个搜索示例。在您的代码中,我没有看到您setFilterSearchRequestBuilder对象上的位置。您似乎也不需要 and 过滤器,因为您使用的是单个过滤器。此外,您可能正在使用默认映射进行索引,因此术语“TX”是小写的。这就是为什么当您使用术语过滤器搜索时找不到任何匹配项的原因。尝试搜索小写的“tx”。

You can either change your mapping if you want to keep the "TX" term as it is while indexing, probably setting the field as not_analyzedif it should only be a single token. Otherwise you can change filter, you might want to have a look at a query that is analyzed, so that your query wil be analyzed the same way the content was indexed.

如果您想在编制索引时保持“TX”术语不变,您可以更改您的映射,可能将字段设置为not_analyzed应该只是一个标记。否则,您可以更改过滤器,您可能希望查看已分析的查询,以便您的查询以与内容编制索引的方式相同的方式进行分析。

Have a look at the query DSL documentationfor more information regarding queries and filters:

有关查询和过滤器的更多信息,请查看查询 DSL 文档

  • MatchAllFilter: matches all your document, not that useful I'd say
  • TermFilter: Filters documents that have fields that contain a term (not analyzed)
  • AndFilter: compound filter used to put in and two or more filters
  • MatchAllFilter: 匹配你所有的文件,我会说没有那么有用
  • TermFilter:过滤具有包含术语的字段的文档(未分析)
  • AndFilter: 复合过滤器用于放入和两个或多个过滤器

Don't know what you mean by InFilterBuilder, couldn't find any filter with this name.

不知道您的意思InFilterBuilder,找不到任何具有此名称的过滤器。

The query usually contains what the user types in through the text search box. Filters are more way to refine the search, for example clicking on facet entries. That's why you would still have the query plus one or more filters.

查询通常包含用户通过文本搜索框输入的内容。过滤器是优化搜索的更多方式,例如单击构面条目。这就是为什么您仍然需要查询加上一个或多个过滤器的原因。

回答by Geert-Jan

To append to what @javanna said:

附加到@javanna 所说的内容:

A lot of confusion can come from the fact that filters can be defined in several ways:

可以通过多种方式定义过滤器这一事实可能会引起很多混淆:

What's the difference you might ask. And indeed you can construct exactly the same logic in both ways.

你可能会问有什么区别。事实上,你可以用两种方式构建完全相同的逻辑。

The difference is that a query operates on BOTH the resultset as well as any facets you have defined. Whereas, a Filter (when defined standalone) only operates on the resultset and NOT on any facets you may have defined (explained here: http://www.elasticsearch.org/guide/reference/api/search/filter/)

不同之处在于查询对结果集以及您定义的任何方面都进行了操作。而过滤器(当独立定义时)仅在结果集上运行,而不在您可能定义的任何方面运行(在此处解释:http: //www.elasticsearch.org/guide/reference/api/search/filter/

回答by James Drinkard

To add to the other answers, InFilter is only used with FilterBuilders. The definition is, InFilter: A filter for a field based on several terms matching on any of them.

要添加到其他答案中,InFilter 仅与 FilterBuilders 一起使用。定义是, InFilter:基于与其中任何一个匹配的多个术语的字段过滤器。

The query Java API uses FilterBuilders, which is a factory for filter builders that can dynamically create a query from Java code. We do this using a form and we build our query based on user selections from it with checkboxes, options, and dropdowns.

查询 Java API 使用 FilterBuilders,它是过滤器构建器的工厂,可以从 Java 代码动态创建查询。我们使用表单来执行此操作,并根据用户从表单中选择的复选框、选项和下拉列表构建我们的查询。

Here is some Example code for FilterBuildersand there is a snippet from that link that uses InFilter as shown below:

这是FilterBuilders 的一些示例代码,该链接中有一个使用 InFilter 的片段,如下所示:

FilterBuilder filterBuilder;
    User user = (User) auth.getPrincipal();
    if (user.getGroups() != null && !user.getGroups().isEmpty()) {
        filterBuilder = FilterBuilders.boolFilter()
                .should(FilterBuilders.nestedFilter("userRoles", FilterBuilders.termFilter("userRoles.key", auth.getName())))
                .should(FilterBuilders.nestedFilter("groupRoles", FilterBuilders.inFilter("groupRoles.key", user.getGroups().toArray())));
    } else {
        filterBuilder = FilterBuilders.nestedFilter("userRoles", FilterBuilders.termFilter("userRoles.key", auth.getName()));
    }
    ...