(五)elasticsearch之查询(Query DSL)

╰+攻爆jí腚メ 2024-04-17 05:46 153阅读 0赞

elasticsearch之查询(Query DSL)

一、字段类查询

字段类查询主要包含以下2类:

  • 全文匹配:针对text 类型的字段进行全文检索,会对查询语句先进行分词处理,如match、match_phrase等query类型
  • 单词匹配:不会对查询语句进行分词处理,直接去匹配字段的倒排索引,如term、terms、range等query 类型

补:match、match_phase、term、query_string的区别

1.term结构化字段查询,匹配一个值,且输入的值不会被分词器分词。

比如查询条件是:

  1. {
  2. "query":{
  3. "term":{
  4. "foo": "hello world"
  5. }
  6. }
  7. }

那么只有在字段中存储了“hello world”的数据才会被返回,如果在存储时,使用了分词,原有的文本“I say hello world”会被分词进行存储,不会存在“hello world”这整个词,那么不会返回任何值。

但是如果使用“hello”作为查询条件,则只要数据中包含“hello”的数据都会被返回,分词对这个查询影响较大。

2.match_phase习语匹配,查询确切的phase,在对查询字段定义了分词器的情况下,会使用分词器对输入进行分词,然后返回满足下述两个条件的document:

1.match_phase中的所有term都出现在待查询字段之中

2.待查询字段之中的所有term都必须和match_phase具有相同的顺序

  1. { "foo":"I just said hello world" }
  2. { "foo":"Hello world" }
  3. { "foo":"World Hello" }

​ 3.使用match_phase:

  1. {
  2. "query": {
  3. "match_phrase": {
  4. "foo": "Hello World"
  5. }
  6. }
  7. }

会返回前两条文档。

注:slop 参数

通过 slop 参数可以控制单词间的间隔,如设置”slop”: “2”,则表示单词间可以隔2个单词。

3.match模糊匹配,先对输入进行分词,对分词后的结果进行查询,文档只要包含match查询条件的一部分就会被返回。

4.query_string语法查询,同match_phase的相同点在于,输入的查询条件会被分词,但是不同之处在与文档中的数据可以不用和query_string中的查询条件有相同的顺序。

5.match之 operator参数

通过 operator 参数可以 控制 单词间的匹配关系,可选项是 or 和 and。

因此,当你希望match 实现 分词 但词语必须都包含的情况时,可以修改此参数来达到目的,如下:

  1. GET testindex/_search
  2. {
  3. "query": {
  4. "match": {
  5. "name" {
  6. "query": "hello world",
  7. "operator": "and"
  8. }
  9. }
  10. }
  11. }

6.match 之 minimum_should_match 参数

通过minimum_should_match 参数可以控制需要匹配的单词数。

例:

  1. // 任意满足其中2个单词即可
  2. GET testindex/_search
  3. {
  4. "query": {
  5. "match": {
  6. "name": {
  7. "query": "i want to say hello",
  8. "minimum_should_match": "2"
  9. }
  10. }
  11. }
  12. }

二、相关性算分

1、介绍

  • 相关系算分是指文档与查询语句之间的相关度。
  • 本质是一个排序问题,排序的依据是相关性算分。

2、相关概念

  • Term Frequency(TF)词频,即单词在该文档中出现的次数。词频越高,相关度越大;
  • Document Frequency(DF)文档频率,即单词出现的文档数;
  • Inverse Document Frequency(IDF)逆向文档频率,与 DF 相反,简单理解是1/DF。即单词出现的文档数越少,相关度越大;
  • Filed-length Norm 文档越短,相关性越大。

3、es 的主要相关性算分模型

  • TF/IDF 模型
  • BM25 模型,5.x之后的默认模型

4、explain 参数(请联想下explain在mysql的作用)

可以通过explain 参数来查看具体的计算方法,但需要主要以下几点:

  • es 的算分是按照shard 进行的,即 shard 的分数计算是相互独立的,所以在使用 explain的时候注意分片数
  • 可以通过设置索引的分片数为 1来避免这个问题

例:

  1. GET testindex/_search
  2. {
  3. "explain": true,
  4. "query": {
  5. "match": {
  6. "name": "kate"
  7. }
  8. }
  9. }
  10. // 设置shards分片数
  11. PUT testindex
  12. {
  13. "settings": {
  14. "index": {
  15. "number_of_shards": "1"
  16. }
  17. }
  18. }

三、复杂查询之 constant_score 查询

  • 该查询将其内部的查询结果文档得分都设定为1 或者boost 的值;
  • 常用于 结合 bool 查询实现自定义得分。

语法如下:

  1. GET testindex/_search
  2. {
  3. "query": {
  4. "constant_score": {
  5. "filter": { // 只能有一个
  6. "match": {
  7. "name": "kate"
  8. }
  9. }
  10. }
  11. }
  12. }

四、复杂查询之 bool 查询

bool 查询可由一个或多个布尔子句组成,主要包含如下4类:






















filter 只过滤符合条件的文档,不计算相关性得分
must 文档必须符合 must中的所有条件,会影响相关性得分
must_not 文档必须不符合 must_not 中的所有条件,不计算相关性得分
should 文档可以符合 should 中的所有条件,会影响相关性得分

1、filter

  • filter 查询只过滤符合条件的文档,不计算相关性得分
  • es针对 filter 会有智能缓存,因此其执行效率很高
  • 做简单匹配查询且不考虑算分时,推荐使用 filter 替代 query 等

语法如下:

  1. GET testindex/_search
  2. {
  3. "query": {
  4. "bool": {
  5. "filter": [
  6. {
  7. "term": {
  8. "name": "kate"
  9. }
  10. }
  11. ]
  12. }
  13. }
  14. }

2、should

should 使用分为2种情况:

(1)bool 查询只包含 should,不包含must查询

此时,文档满足一个条件即可。

可通过minimum_should_match 来控制满足条件的个数。

(2)bool 查询同时包含 should 和 must查询

此时,文档必须满足must 的条件,should可以不满足,但是如果满足了should 条件,会增加相关性得分。

五、其他 api

1、_count

统计文档数目

2、_source

过滤返回结果中 _source 中的字段,主要有以下几种用法

  1. 用法一:
  2. GET testindex/_search?_source=name
  3. 用法二:
  4. GET testindex/_search
  5. {
  6. "_source": false
  7. }
  8. 用法三:
  9. GET testindex/_search
  10. {
  11. "_source": ["name","age"]
  12. }
  13. 用法四:
  14. GET testindex/_search
  15. {
  16. "_source": {
  17. "includes": "name",
  18. "excludes": "age"
  19. }
  20. }

六、常见的查询问题

1、查询字段是否存在

  1. GET testindex/_search
  2. {
  3. "query": {
  4. "exists": { // 关键字
  5. "field": "price" // price 字段
  6. }
  7. }
  8. }

2、查询空字符串的字段(字段存在,内容是空字符串)

  1. // 利用 wildcardQuery 和 mustNot搭配,可以查到空字符串内容的值
  2. BoolQueryBuilder mustNot = QueryBuilders.boolQuery()
  3. .must(QueryBuilders.existsQuery("group_name"))
  4. .mustNot(QueryBuilders.wildcardQuery("group_name", "*"));

发表评论

表情:
评论列表 (有 0 条评论,153人围观)

还没有评论,来说两句吧...

相关阅读