当前位置:   article > 正文

elasticsearch-java api之过滤_es postfilter java

es postfilter java

一、过滤相关点:

1、查询与过滤:

Elasticsearch 使用的查询语言(DSL) 拥有一套查询组件,这些组件可以以无限组合的方式进行搭配。这套组件可以在以下两种情况下使用:过滤情况(filtering context)和查询情况(query context)。

当使用于 过滤情况 时,查询被设置成一个“不评分”或者“过滤”查询。即,这个查询只是简单的问一个问题:“这篇文档是否匹配?”。回答也是非常的简单,yes 或者 no ,二者必居其一。

  • created 时间是否在 2013 与 2014 这个区间?
  • status 字段是否包含 published 这个单词?
  • lat_lon 字段表示的位置是否在指定点的 10km 范围内?
当使用于 查询情况 时,查询就变成了一个“评分”的查询。和不评分的查询类似,也要去判断这个文档是否匹配,同时它还需要判断这个文档匹配的有 _多好_(匹配程度如何)。 此查询的典型用法是用于查找以下文档:
  • 查找与 full text search 这个词语最佳匹配的文档
  • 包含 run 这个词,也能匹配 runs 、 running 、 jog 或者 sprint
  • 包含 quick 、 brown 和 fox 这几个词 — 词之间离的越近,文档相关性越高
  • 标有 lucene 、 search 或者 java 标签 — 标签越多,相关性越高
一个评分查询计算每一个文档与此查询的 _相关程度_,同时将这个相关程度分配给表示相关性的字段 `_score`,并且按照相关性对匹配到的文档进行排序。这种相关性的概念是非常适合全文搜索的情况,因为全文搜索几乎没有完全 “正确” 的答案。

说明:

自 Elasticsearch 问世以来,查询与过滤(queries and filters)就独自成为 Elasticsearch 的组件。但从 Elasticsearch 2.0 开始,过滤(filters)已经从技术上被排除了,同时所有的查询(queries)拥有变成不评分查询的能力

然而,为了明确和简单,我们用 "filter" 这个词表示不评分、只过滤情况下的查询。你可以把 "filter" 、 "filtering query" 和 "non-scoring query" 这几个词视为相同的。相似的,如果单独地不加任何修饰词地使用 "query" 这个词,我们指的是 "scoring query" 。


2、性能差异:

过滤查询(Filtering queries)只是简单的检查包含或者排除,这就使得计算起来非常快。考虑到至少有一个过滤查询(filtering query)的结果是 “稀少的”(很少匹配的文档),并且经常使用不评分查询(non-scoring queries),结果会被缓存到内存中以便快速读取,所以有各种各样的手段来优化查询结果。相反,评分查询(scoring queries)不仅仅要找出 匹配的文档,还要计算每个匹配文档的相关性,计算相关性使得它们比不评分查询费力的多。同时,查询结果并不缓存。

多亏倒排索引(inverted index),一个简单的评分查询在匹配少量文档时可能与一个涵盖百万文档的filter表现的一样好,甚至会更好。但是在一般情况下,一个filter 会比一个评分的query性能更优异,并且每次都表现的很稳定。过滤(filtering)的目标是减少那些需要通过评分查询(scoring queries)进行检查的文档。

参考:https://www.elastic.co/guide/cn/elasticsearch/guide/current/_queries_and_filters.html


二、过滤实例:

在之前es版本(2.0之前)的官网中,介绍了两种过滤:一个是Filtered Query,一个是Post Filter。前者是先使用filter,过滤后的结果再query;后者是先query,query的结果再过滤。而在es中,filter的操作使用了cache,速度比query快。

在最新2.0版本的官网上中,提到了:

现在是时候忘掉你所知道的关于查询和过滤器的一切了:Elasticsearch 2.0将自己做出更好的决定,而不是依靠用户来制定一个优化的查询。这一变化在API层面几乎是看不见的,但是让我们来深入探讨使之成为可能的内部变化。本篇文章中提到的大部分更改都是在Lucene 5.0,5.1和5.2中完成的,并将集成到Elasticsearch 2.0中。

在Elasticsearch 2.0中,查询和过滤器是相同的内部对象,可以配置这些对象来评分文档或跳过评分。然后,查询DSL确保正确传播信息:例如,如果bool查询需要产生分数,则bool查询的must子句将需要产生分数,而must_not子句永远不需要产生分数,因为它可能只是用于过滤文件。为了使查询的DSL更加符合这种变化,我们已经废弃了过滤的查询,赞成在bool查询中使用一个新的过滤器子句:过滤器子句就像must子句,除了它们没有贡献分数。意味着:

  1. {
  2. “filtered” : {
  3. “query”: { query definition },
  4. “filter”: { filter definition }
  5. }
  6. }
应该被替代成:

  1. {
  2. “bool” : {
  3. “must”: { query definition },
  4. “filter”: { filter definition }
  5. }
  6. }
注:查询DSL仍然是向后兼容的,尽管有这种改变:如果你尝试运行一个过滤的查询,它将在内部解析为一个bool查询。但是,我们鼓励您迁移到新的语法,因为在未来的发行版中,已过滤的查询将被删除。


实例1:postfilter

  1. public static void filterQuery1(String indexName,String indexType) {
  2. QueryBuilder qb = QueryBuilders.boolQuery()
  3. .must(QueryBuilders.constantScoreQuery(QueryBuilders.matchQuery("title", "java")).boost(1f))
  4. .should(QueryBuilders.constantScoreQuery(QueryBuilders.termQuery("title", "elasticsearch")).boost(5f))
  5. .should(QueryBuilders.termQuery("title", "hadoop"));
  6. QueryBuilder fb = QueryBuilders.rangeQuery("age").from(10).to(20);
  7. SearchResponse searchResponse = transportClient.prepareSearch(indexName).setTypes(indexType)
  8. .setQuery(qb)
  9. .setPostFilter(fb)
  10. .get();
  11. SearchHits hits = searchResponse.getHits();
  12. //long totalHits = hits.getTotalHits();
  13. SearchHit[] hits2 = hits.getHits();
  14. for (SearchHit sh:hits2) {
  15. Map<String, Object> source = sh.getSource();
  16. String id = sh.getId();
  17. float score = sh.getScore();
  18. System.out.println("source:"+source+",id:"+id+",score:"+score);
  19. }
  20. }
注:使用QueryBuilder创建过滤(代替了之前版本的FilterBuilder)

实例2:filter

  1. public static void filterQuery2(String indexName,String indexType) {
  2. QueryBuilder qb = QueryBuilders.boolQuery()
  3. .must(QueryBuilders.constantScoreQuery(QueryBuilders.matchQuery("title", "java")).boost(1f))
  4. .should(QueryBuilders.constantScoreQuery(QueryBuilders.termQuery("title", "elasticsearch")).boost(5f))
  5. .should(QueryBuilders.termQuery("title", "hadoop"))
  6. .filter(QueryBuilders.rangeQuery("age").from(10).to(20));
  7. System.out.println(qb.toString());
  8. SearchResponse searchResponse = transportClient.prepareSearch(indexName).setTypes(indexType)
  9. .setQuery(qb)
  10. .get();
  11. SearchHits hits = searchResponse.getHits();
  12. //long totalHits = hits.getTotalHits();
  13. SearchHit[] hits2 = hits.getHits();
  14. for (SearchHit sh:hits2) {
  15. Map<String, Object> source = sh.getSource();
  16. String id = sh.getId();
  17. float score = sh.getScore();
  18. System.out.println("source:"+source+",id:"+id+",score:"+score);
  19. }
  20. }
A、之前这种写法已经被废弃:QueryBuilders. filteredQuery(qb, qb);
B、对于Filtered Query已经被bool查询+filter替代,我们可以手工在bool查询中指定filter,同时es内部将bool查询也会自动优化成filter。例如:

  1. QueryBuilder qb = QueryBuilders.boolQuery()
  2. .must(QueryBuilders.constantScoreQuery(QueryBuilders.matchQuery("title", "java")).boost(1f))
  3. .should(QueryBuilders.constantScoreQuery(QueryBuilders.termQuery("title", "elasticsearch")).boost(5f))
  4. .should(QueryBuilders.termQuery("title", "hadoop"));
  5. System.out.println(qb.toString());
这样的boolean查询,会被优化成如下的dsl:

  1. {
  2. "bool" : {
  3. "must" : {
  4. "constant_score" : {
  5. "filter" : {
  6. "match" : {
  7. "title" : {
  8. "query" : "java",
  9. "type" : "boolean"
  10. }
  11. }
  12. },
  13. "boost" : 1.0
  14. }
  15. },
  16. "should" : [ {
  17. "constant_score" : {
  18. "filter" : {
  19. "term" : {
  20. "title" : "elasticsearch"
  21. }
  22. },
  23. "boost" : 5.0
  24. }
  25. }, {
  26. "term" : {
  27. "title" : "hadoop"
  28. }
  29. } ]
  30. }
  31. }
参考:

https://www.elastic.co/blog/better-query-execution-coming-elasticsearch-2-0

https://www.elastic.co/guide/en/elasticsearch/reference/2.0/breaking_20_java_api_changes.html

https://www.elastic.co/guide/cn/elasticsearch/guide/current/_filter_bucket.html



声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/运维做开发/article/detail/817739
推荐阅读
相关标签
  

闽ICP备14008679号