ElasticSearch学习总结(三):查询总结

本文主要对Elasticsearch中查询相关的知识做一个简单的总结,内容主要包括查询的评分机制,查询改写,过滤器,以及对常见的查询做一个简单的分类

1. 评分机制

在Lucense中默认使用TF/IDF算法对文档进行评分,该算法已经在前文做了简单的介绍,这里主要总结下什么样的因素可能得到高分
1. 越罕见的词被匹配上,得分越高。
2. 文档字段越短(包含更少的词项),文档的得分越高
3. 权重越高(可以是索引期或是查询期赋予的权重),得分越高

Elasticsearch 提供的评分算法比较丰富(默认为BM25),可以通过similarity进行配置,可配置的项目包括:
1. BM25
2. Classic(基于TF/IDF)
3. DFR/DFI
4. IB
5. ….
关于每个算法的介绍以及可配置参数可以参见:https://www.elastic.co/guide/en/elasticsearch/reference/5.2/index-modules-similarity.html

另外需要注意的是除了使用similarity进行评分的控制之外,还可以通过function_score,constant_score,rescore 等多种机制对评分进行更加精确的控制。

2. 查询改写

在进行==前缀查询==或是==通配符查询==时,实际上会转化为对多个关键词的查询,处于性能优化的考虑,Lucene会把这种查询转化为一组开销较小的查询方式,采取的主要手段便是“查询改写(rewrite)”

查询改写使用的主要策略为通过使用常量得分查询(constant score query)来代替常规查询来减少查询时性能的开销,对于可能匹配term较多的查询时,性能提升尤为明显。

在查询改写的过程中可以根据需要自定义改写的方式,可支持的配置如下

  • scoring_boolean:该选项将每个生成的词项转化为布尔查询中的一个或从句(Boolean should clause)。这种改写方法需要针对每个文档都计算得分。因此,这种方法比较耗费CPU,而且有些查询生成了太多的词项,以至于超出了布尔查询默认的1024个从句的限制。默认的布尔查询限制可以通过设置Elasticsearch.yml文件的index.query.bool.max_clause_count属性来修改。改写后的布尔查询的从句数越多,查询性能越低
  • constant_score_boolean:该选项与前面提到过的scoring_boolean类似,但是CPU耗费更少,这是因为并不计算每个从句的得分,而是每个从句得到一个与查询权重相同的一个常数得分,默认情况下等于1,我们也可以通过设置查询权重来改变这个默认值。与scoring_boolean类似,该选项也有布尔从句数的限制。
  • constant_score(==默认选项==):在匹配的词项较少时,与constant_score_boolean类似,匹配的词项较多时,会遍历并查询所有的词项,然后使用相同的常数得分。
  • top_terms_N:与scoring_boolean相似之处在于都会对从句计算得分,不同之处在于,该方法只保留最佳的N个词项,以避免触及布尔从句数的限制,并提升查询整体性能。
  • top_terms_boost_N:该选项与top_terms_N类似,不同之处在于它的文档得分不是通过计算得出的,而是被设置为跟查询权重(boost)一致,默认值为1。

对于如何选择rewrite配置的问题,可以遵循如下原则
- 如果您能接受较低的精度和相关性(但是追求更高的性能),那么可以采用top-N查询改写方法。
- 如果您需要更高的查询精度和更好的相关性(同时可以接受较低的性能),那么应该采用布尔方法。

3. 过滤器

3.1 过滤器的作用

Elsaticsearch在提供了丰富查询功能的同时,还提供了过滤器的功能,过滤器的作用顾名思义,主要用来对查询结果过滤,但过滤的过程中不会涉及到store的计算性能损耗(是不会对已有查询的store造成影响),同时频繁使用的过滤器还会被Elasticsearch自动的缓存,总而提高查询的性能。

3.2 工作原理

过滤器持有的关于文档的唯一重要信息是该文档是否匹配这个过滤器(仅仅一个标记而已)

过滤器通过返回一个被称为DocIdSet(org.apache.lucene.search.DocIdSet)的数据结构来提供匹配信息。这个数据结构的用途是为索引段提供经过滤器过滤后的数据。它可以使用Bits接口(org.apache.lucene.util.Bits)的有关实现。Bits接口可以随机访问过滤器中的文档信息(主要是检查索引段中的某个文档是否和该过滤器匹配)。

Bits的数据结构非常高效,因为CPU可以使用位运算来完成过滤

下面的表格展示了Bits接口的工作方式

doc bits.get(doc) Result
1 False
2 False
3 True 3
4 True 4

Elasticsearch和Lucene可以根据不同的使用场景选择不同的DocIdSet实现,不是所有的过滤器都使用Bits结构,比如数值区间过滤器、脚本过滤器、以及基于地理位置的一组过滤器。这些特殊的过滤器选择把数据记录在字段缓存里,然后再遍历所需处理的文档集合,逐个进行过滤操作。这意味着过滤器链条中的下一个过滤器只能获取到匹配前一个过滤器的文档集合。因此,可以针对这些过滤器进行优化,比如把最重的(匹配文档最多的,或者性能最差的)过滤器放到过滤器链的最后去执行。

4. 查询的分类

本章节主要总结Elasticsearch支持的常见查询类型并进行分类,由于Elasticsearch的查询功能较多,本部分只会选择性的进行说明,具体使用方法与参数可以参见官方文档:https://www.elastic.co/guide/en/elasticsearch/reference/5.2/query-dsl.html

4.1 查询方法

在不使用API的情况下,可以使用两种方式对数据进行查询

  • URL查询
curl -XGET 'localhost:9200/twitter/tweet/_search?q=user:kimchy&pretty'
  • Request Body 查询
curl -XGET 'localhost:9200/twitter/tweet/_search?pretty' -H 'Content-Type: application/json' -d'
{
    "query" : {
        "term" : { "user" : "kimchy" }
    }
}
'

4.2 查询分类

4.2.1 基本查询

这类查询通常作为其他复杂查询的一部分,或是单独传递给Elasticsearch进行查询

  • match查询:该查询会对==查询词==进行分词,分词后查询语句中的任何一个词项被匹配,文档就会被搜索到。
  • match_all查询:该查询会返回所有的文档。
  • term查询:该查询的查询词==不会被分词==。只有文档中的词和查询词精确匹配时才会被搜索到。
  • query_string查询:该查询允许在一个查询中使用多个特殊的条件关键字进行查询(例如 AND|OR|NOT)对多个字段进行查询
  • 其他:match,multi_match,fuzzy_like_this,ids,query_string,simple_query_string,range,prefix,term,terms等等

4.2.2 组合查询

该种类型的查询可以嵌入其他查询以及过滤器
- bool查询:比较常用的组合查询,可以把多个查询用布尔逻辑组织在一起。
- dis_max查询:该种查询的结果文档得分和最高权重的子查询打分高度相关,如果希望最高得分的子查询能够在打分过程中起决定性的作用,可以使用该类查询
- 其他:bool,boosting,dis_max,has_child,nested,span-XXX等

4.2.3 无分析查询

该种类型的输入不会被分析,而是直接原样传递给lucene

相关查询主要包括:term,common,ids,prefix,wildcard等等

4.2.4 全文检索查询

当需要构建类似于Google这样的查询时,可以使用该类查询,该类查询会根据输入与配置进行查询结果的打分操作。
相关查询主要包括:match,multi_match,query_string,simple_query_string等

4.2.5 模式匹配查询

顾名思义,该类查询主要是用来支持通配符查询的。需要注意的是该类查询的资源损耗一般都比较大

相关查询主要包括:prefix,regrex,wildcard

4.2.6 相似度查询

该类查询典型的应用场景为近似词查询,或是提供类似于Google的”你想找的是不是XXX”的功能

相关查询主要包括:fuzzy_like_this,fuzzy_like_this_field,more_like_this等

4.2.7 打分相关的查询

该类查询可以通过自定义权重的方式来改善查询精度或是查询得分。

相关查询主要包括:boosting,constant_score,function_score,indices

4.2.8 位置敏感查询

可以使用索引中存储的词项位置作为查询条件的查询,例如 “需要查询masting以及elasticsearch两个词项,且这连个单词相互临近,顺序必须是masting在前面,前后距离还不超过3个位置”

该类查询的开销也很大,需要消耗大量的CPU资源

相关查询主要包括:match_phrase,span_XXX

4.2.9 结构敏感查询

该种类型的查询可以提供类似于SQL中Join的关系查询
- nested查询:文档中可以包含嵌套类型的字段,这些字段可以用来索引一些数组对象,每个对象都可以单独的查询,详细细节可以参考官方文档的nested类型(https://www.elastic.co/guide/en/elasticsearch/reference/5.2/nested.html),以及nested查询(https://www.elastic.co/guide/en/elasticsearch/reference/5.2/query-dsl-nested-query.html)

  • 其他: has_child,has_parent

4.2.10 地理位置查询

该类查询主要针对geo_point的查询以及geo_shape

相关查询主要包括:geo_distance,geo_bounding_box,geo_polygon,geo_shape

4.2.11 搜索高亮查询

该类查询主要通过对查询结果使用默认标签()或是自定义标签的方式来实现查询结果高亮的应用场景

相关查询主要包括:highlighter,fast_vector_highlighter

4.2.12 搜索排序

Elasticsearch中默认的查询结果是按照评分排序的,可以使用sort进行排序

4.2.13 其他

  • script查询:可以使用脚本进行查询
  • percolate查询:该类查询需要先注册查询条件,然后更具文档来查询条件,常见的使用场景包括:数据分类,数据路由,时间监控等

猜你喜欢

转载自blog.csdn.net/sun7545526/article/details/79413668
今日推荐