• 重学Elasticsearch第3章 : ElasticSearch高级查询、索引库原理、倒排索引、DSL高级检索



    ES中高级检索(Query)

    检索: 索: 对文档创建索引的过程; 检: 检索,根据查询条件查询文档

    检索方式 _search

    ES官方提供了两中检索方式:

    • 一种是通过 URL 参数进行搜索
    • `另一种是通过 DSL(Domain Specified Language) 进行搜索官方更推荐使用第二种方式第二种方式是基于传递JSON作为请求体(request body)格式与ES进行交互,这种方式更强大,更简洁

    在这里插入图片描述

    • 使用语法

      URL查询: GET /索引/类型/_search?参数

      DSL查询: GET /索引/类型/_search {}

    给索引添加测试数据

    1.删除索引
    DELETE /ems
    
    // 表示删除成功
    {
      "acknowledged" : true
    }
    
    2.创建索引并指定类型
    PUT /ems
    {
      "mappings":{
          "properties":{
            "name":{
              "type":"text"
            },
            "age":{
              "type":"integer"
            },
            "bir":{
              "type":"date"
            },
            "content":{
              "type":"text"
            },
            "address":{
              "type":"keyword"
            }
        }
      }
    }
    
    3.插入测试数据
    PUT /ems/_bulk
      {"index":{}}
      {"name":"小黑","age":23,"bir":"2012-12-12","content":"为开发团队选择一款优秀的MVC框架是件难事儿,在众多可行的方案中决择需要很高的经验和水平","address":"北京"}
      {"index":{}}
      {"name":"王小黑","age":24,"bir":"2012-12-12","content":"Spring 框架是一个分层架构,由 7 个定义良好的模块组成。Spring 模块构建在核心容器之上,核心容器定义了创建、配置和管理 bean 的方式","address":"上海"}
      {"index":{}}
      {"name":"张小五","age":8,"bir":"2012-12-12","content":"Spring Cloud 作为Java 语言的微服务框架,它依赖于Spring Boot,有快速开发、持续交付和容易部署等特点。Spring Cloud 的组件非常多,涉及微服务的方方面面,井在开源社区Spring 和Netflix 、Pivotal 两大公司的推动下越来越完善","address":"无锡"}
      {"index":{}}
      {"name":"win7","age":9,"bir":"2012-12-12","content":"Spring的目标是致力于全方位的简化Java开发。 这势必引出更多的解释, Spring是如何简化Java开发的?","address":"南京"}
      {"index":{}}
      {"name":"梅超风","age":43,"bir":"2012-12-12","content":"Redis是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API","address":"杭州"}
      {"index":{}}
      {"name":"张无忌","age":59,"bir":"2012-12-12","content":"ElasticSearch是一个基于Lucene的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口","address":"北京"}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46

    URL检索

    • queryString方式就是URL检索,跟上?q=

    GET /ems/_search?q=*&sort=age:asc

    ​ _search 搜索的API
    ​ q=* 匹配所有文档
    ​ sort 以结果中的指定字段排序

    GET /ems/emp/_search?q=*&sort=age:desc&size=5&from=0&_source=name,age,bir

    # QueryString的查询方式
    
    #1.查询所有
    GET /ems/_search?q=*
    
    #2.排序 sort
    GET /ems/_search?q=*&sort=age
    GET /ems/_search?q=*&sort=age:desc
    
    #3.分页 from size (es默认展示10)
    GET /ems/_search?q=*&sort=age:desc&size=2&from=0
    
    #4.指定展示的字段_source
    GET /ems/_search?q=*&_source=name,age
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    DSL检索 (重点)

    NOTE: 以下重点讲解DSL语法

    # QueryDSL查询方式
    
    # 查询所有文档
    GET /ems/_search
    {
      "query": {
        "match_all":{}
      }
    }
    
    #1.排序 (text不支持排序,keyword支持)
    GET /ems/_search
    {
      "query": {
        "match_all": {}
      },
      "sort": [
        {
          "age": {
            "order": "desc"
          }
        },
        {
          "address":{
            "order": "desc"
          }
        }
      ]
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    在这里插入图片描述

    DSL高级检索(Query) (重点)

    0. 查询所有(match_all)

    match_all关键字: 返回索引中的全部文档

    GET /ems/_search
    {
     	"query": { "match_all": {} }
    }	
    
    • 1
    • 2
    • 3
    • 4

    1. 查询结果中返回指定条数(size)

    size 关键字: 指定查询结果中返回指定条数。 默认返回值10条

    GET /ems/_search
    {
     	"query": { "match_all": {} },
    	"size": 1  // 返回一条文档
    }	
    
    • 1
    • 2
    • 3
    • 4
    • 5

    在这里插入图片描述

    2. 分页查询(from)

    from 关键字: 用来指定起始返回位置,和size关键字连用可实现分页效果

    // 检索出第2页2条文档,并按age进行倒序
    GET /ems/_search
    {
          "query": {"match_all": {}},
          "sort": [
            {
              "age": {
                "order": "desc"
              }
            }
          ],
          "size": 2, 
          "from": 1
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    3. 查询结果中返回指定字段(_source)

    _source 关键字: 是一个数组,在数组中用来指定展示那些字段

    // 检索出所有文档,文档中只展示accout_number, balance两个字段
    GET /ems/_search
    {
          "query": { "match_all": {} },
          "_source": ["name", "address"]
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    在这里插入图片描述

    4. 关键词查询(term)

    term 关键字: 用来使用关键词查询

    // 检索出address字段为北京的文档
    GET /ems/_search
    {
      "query": {
        "term": {
          "address": {
            "value": "北京"
          }
        }
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    在这里插入图片描述

    提示1: 通过使用term查询得知ES中默认使用分词器为标准分词器(StandardAnalyzer),

    标准分词器对于英文单词分词,对于中文单字分词

    提示2: 通过使用term查询得知,在ES的Mapping Type 中 keyword , date ,integer, long , double , boolean or ip 这些类型不分词只有text类型分词

    索引库原理 (倒排索引)

    在这里插入图片描述

    注意: 一个es索引分为索引区元数据区, 索引区用来存储文档分词后的数据, 元数据区是用来存储源数据;

    • 上图是采用默认的分词器,对中文会进行单字分词; 索引区对json中每个key的value值进行分词分析,统计出次数;
      eg: address的类型为keyword所以不会分词; [北京:0,1]表示北京这个词在索引号0的文档中出现1次,得1分

    当我们查询的时候,首先去索引区进行匹配索引号,然后根据最佳匹配的索引号,再去元数据区击中文档

    倒排索引

    • Elasticsearch使用一种称为倒排索引的结构,它适用于快速的全文搜索。

    • 见其名,知其意,有倒排索引,肯定会对应有正向索引。正向索引(forward index),反向索引(inverted index)更熟悉的名字是倒排索引。

    • 所谓的正向索引,就是搜索引擎会将待搜索的文件都对应一个文件ID,搜索时将这个ID和搜索关键字进行对应,形成K-V对,然后对关键字进行统计计数。
      在这里插入图片描述
      但是互联网上收录在搜索引擎中的文档的数目是个天文数字,这样的索引结构根本无法满足实时返回排名结果的要求。所以,搜索引擎会将正向索引重新构建为倒排索引,即把文件ID对应到关键词的映射转换为关键词到文件ID的映射,每个关键词都对应着一系列的文件,这些文件中都出现这个关键词。
      在这里插入图片描述

    倒排索引例子

    在这里插入图片描述

    5. 范围查询(range)

    range 关键字: 用来指定查询指定范围内的文档

    // 检索age大于等于8,小于等于30的文档
    GET /ems/_search
    {
      "query": {
        "range": {
          "age": {
            "gte": 8,
            "lte": 30
          }
        }
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    在这里插入图片描述

    6. 前缀查询(prefix)

    prefix 关键字: 用来检索含有指定前缀的关键词的相关文档

    // 检索出conten字段,前缀为redis的文档
    GET /ems/_search
    {
      "query": {
        "prefix": {
          "content": {
            "value": "redis"
          }
        }
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    在这里插入图片描述

    7. 通配符查询(wildcard)

    wildcard 关键字: 通配符查询 ? 用来匹配一个任意字符, * 用来匹配多个任意字符

    // 检索出content字段中有re*的文档
    GET /ems/_search
    {
      "query": {
        "wildcard": {
          "content": {
            "value": "re*"
          }
        }
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    在这里插入图片描述

    8. 多id查询(ids)

    ids 关键字 : 值为数组类型,用来根据一组id获取多个对应的文档

    // 根据多个id,来检索多个文档
    GET  /ems/_search
    {
      "query": {
        "ids": {
          "values": ["yvahXIIBmuTGHEKH0GHy","zPahXIIBmuTGHEKH0GHy"]
        }
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    在这里插入图片描述

    9. 模糊查询(fuzzy)

    fuzzy 关键字: 用来模糊查询含有指定关键字的文档

    // 检索content字段中spring的文档,spting也可以检索出来,fuzzy规则允许
    GET /ems/_search
    {
      "query": {
        "fuzzy": {
          "content":"spring" //下面两种查询出来的文档一样
          //"content":"spting"
          //"content":"sptlng"
        }
      }
    }
    
    fuzzy 模糊查询  最大模糊错误 必须在0-2之间
    # 搜索关键词长度为 2 不允许存在模糊 0
    # 搜索关键词长度为3-5 允许一次模糊 0 1 
    # 搜索关键词长度大于5 允许最大2模糊
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    在这里插入图片描述

    10. 布尔查询(bool) (重点)

    bool 关键字: 用来组合多个条件实现复杂查询

    must: 相当于&& 同时成立

    should: 相当于|| 成立一个就行

    must_not: 相当于! 不能满足任何一个

    // bool组合了must,must_not来做检索
    	// must: age字段大于0,小于30的文档
    	// must_not: content字段没有redis?的文档
    // 最后按照age倒序展示
    GET /ems/_search
    {
      "query": {
        "bool": {
          "must": [
            {
              "range": {
                "age": {
                  "gte": 0,
                  "lte": 30
                }
              }
            }
          ],
          "must_not": [
            {
            	"wildcard": {
              	"content": {
                	"value": "redi?"
              }
            }}
          ]
        }
      },
      "sort": [
        {
          "age": {
            "order": "desc"
          }
        }
      ]
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    {
      "took" : 1,
      "timed_out" : false,
      "_shards" : {
        "total" : 1,
        "successful" : 1,
        "skipped" : 0,
        "failed" : 0
      },
      "hits" : {
        "total" : {
          "value" : 4,
          "relation" : "eq"
        },
        "max_score" : null,
        "hits" : [
          {
            "_index" : "ems",
            "_type" : "_doc",
            "_id" : "yfahXIIBmuTGHEKH0GHy",
            "_score" : null,
            "_source" : {
              "name" : "王小黑",
              "age" : 24,
              "bir" : "2012-12-12",
              "content" : "Spring 框架是一个分层架构,由 7 个定义良好的模块组成。Spring 模块构建在核心容器之上,核心容器定义了创建、配置和管理 bean 的方式",
              "address" : "上海"
            },
            "sort" : [
              24
            ]
          },
          {
            "_index" : "ems",
            "_type" : "_doc",
            "_id" : "yPahXIIBmuTGHEKH0GHy",
            "_score" : null,
            "_source" : {
              "name" : "小黑",
              "age" : 23,
              "bir" : "2012-12-12",
              "content" : "为开发团队选择一款优秀的MVC框架是件难事儿,在众多可行的方案中决择需要很高的经验和水平",
              "address" : "北京"
            },
            "sort" : [
              23
            ]
          },
          {
            "_index" : "ems",
            "_type" : "_doc",
            "_id" : "y_ahXIIBmuTGHEKH0GHy",
            "_score" : null,
            "_source" : {
              "name" : "win7",
              "age" : 9,
              "bir" : "2012-12-12",
              "content" : "Spring的目标是致力于全方位的简化Java开发。 这势必引出更多的解释, Spring是如何简化Java开发的?",
              "address" : "南京"
            },
            "sort" : [
              9
            ]
          },
          {
            "_index" : "ems",
            "_type" : "_doc",
            "_id" : "yvahXIIBmuTGHEKH0GHy",
            "_score" : null,
            "_source" : {
              "name" : "张小五",
              "age" : 8,
              "bir" : "2012-12-12",
              "content" : "Spring Cloud 作为Java 语言的微服务框架,它依赖于Spring Boot,有快速开发、持续交付和容易部署等特点。Spring Cloud 的组件非常多,涉及微服务的方方面面,井在开源社区Spring 和Netflix 、Pivotal 两大公司的推动下越来越完善",
              "address" : "无锡"
            },
            "sort" : [
              8
            ]
          }
        ]
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83

    11. 高亮查询(highlight)

    highlight 关键字: 可以让符合条件的文档中的关键词高亮

    // 将content字段中redis关键词进行高亮
    GET /ems/_search
    {
      "query": {
        "term": {
          "content": {
            "value": "redis"
          }
        }
      },
      "highlight": {
        "fields": {
          "*": {}
        }
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    在这里插入图片描述

    自定义高亮html标签: 可以在highlight中使用pre_tagspost_tags

    // 根据设置的pre_tags和post_tags来自定义高亮情况
    GET /ems/_search
    {
      "query":{
        "term":{
          "content":"redis"
        }
      },
      "highlight": {
        "pre_tags": [""],
        "post_tags": [""],
        "fields": {
          "content":{}
        }
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    在这里插入图片描述

    多字段高亮 使用require_field_match开启多个字段高亮

    // 将content字段中文档中包含redis的关键词高亮
     GET /ems/_search
    {
      "query":{
        "term":{
          "content":"redis"
        }
      },
      "highlight": {
        "pre_tags": [""],
        "post_tags": [""],
        "require_field_match":false,
        "fields": {
          "*":{}
        }
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    12. 多字段查询(multi_match)

    • 如果搜索的字段分词, 会对query进行 先分词 再搜索
    • 如果搜索的字段不分词,他会直接使用query整体进行字段搜索
    // 将要检索的关键词,在多个字段中进行检索,符合的文档,都检索出来
    // 王小, 在name,content字段中进行检索
    
    // 查询的fields的类型,看该字段是否会分词(只有text会分词)
    // name和content都是text类型,所以会进行分词查询,因为现在使用的是标准分词
    // 所以对中文进行单字分词;王小分为王和小,分别在name,content字段中进行检索
    GET /ems/_search
    {
      "query": {
        "multi_match": {
          "query": "王小",
          "fields": ["name","content"]
        }
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    {
      "took" : 1,
      "timed_out" : false,
      "_shards" : {
        "total" : 1,
        "successful" : 1,
        "skipped" : 0,
        "failed" : 0
      },
      "hits" : {
        "total" : {
          "value" : 3,
          "relation" : "eq"
        },
        "max_score" : 1.6131543,
        "hits" : [
          {
            "_index" : "ems",
            "_type" : "_doc",
            "_id" : "yfahXIIBmuTGHEKH0GHy",
            "_score" : 1.6131543,
            "_source" : {
              "name" : "王小黑",
              "age" : 24,
              "bir" : "2012-12-12",
              "content" : "Spring 框架是一个分层架构,由 7 个定义良好的模块组成。Spring 模块构建在核心容器之上,核心容器定义了创建、配置和管理 bean 的方式",
              "address" : "上海"
            }
          },
          {
            "_index" : "ems",
            "_type" : "_doc",
            "_id" : "yPahXIIBmuTGHEKH0GHy",
            "_score" : 1.498922,
            "_source" : {
              "name" : "小黑",
              "age" : 23,
              "bir" : "2012-12-12",
              "content" : "为开发团队选择一款优秀的MVC框架是件难事儿,在众多可行的方案中决择需要很高的经验和水平",
              "address" : "北京"
            }
          },
          {
            "_index" : "ems",
            "_type" : "_doc",
            "_id" : "yvahXIIBmuTGHEKH0GHy",
            "_score" : 1.1312833,
            "_source" : {
              "name" : "张小五",
              "age" : 8,
              "bir" : "2012-12-12",
              "content" : "Spring Cloud 作为Java 语言的微服务框架,它依赖于Spring Boot,有快速开发、持续交付和容易部署等特点。Spring Cloud 的组件非常多,涉及微服务的方方面面,井在开源社区Spring 和Netflix 、Pivotal 两大公司的推动下越来越完善",
              "address" : "无锡"
            }
          }
        ]
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58

    13. 多字段分词查询(query_string)

    // 因为analyzer为ik最大分词,所以中国声音分为中国,声音
    // 将中国,声音分别在name,content字段中进行检索,符合条件的文档查询出来
    GET /ems/_search
    {
      "query": {
        "query_string": {
          "query": "中国声音",
          "analyzer": "ik_max_word",  // ik分词
          "fields": ["name","content"]
        }
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
  • 相关阅读:
    Zookeeper:实现“通知协调”的 Demo
    滑动窗口的理念
    力扣剑指Offer(每日打卡)
    【Redis高级篇】分片集群--并发
    Java培训之java8新特性程序代码
    2023 年最新 Docker 容器技术基础详细教程(更新中)
    深入探索Spring Boot的条件装配与条件注解
    成长的记录
    【JavaWeb】Tomcat部署Web项目以及Maven工具的使用
    简单谈下Spring、Spring MVC和Spring Boot
  • 原文地址:https://blog.csdn.net/m0_37989980/article/details/126118223