PassJava 开源项目(二十)之 详解 Elasticsearch 高级检索玩法

Posted 公众号_悟空聊架构

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了PassJava 开源项目(二十)之 详解 Elasticsearch 高级检索玩法相关的知识,希望对你有一定的参考价值。

PassJava (佳必过) 项目全套学习教程连载中,关注公众号悟空聊架构第一时间获取。

文档在线地址: www.passjava.cn

ElastiscSearch 系列文章的内容如下:

ElasticSearch 高阶检索玩法

5.1 两种查询方式

5.1.1 URL 后接参数

GET bank/_search?q=*&sort=account_number: asc

``/_search?q=*&sort=account_number: asc

查询出所有数据,共 1000 条数据,耗时 1ms,只展示 10 条数据 ( ES 分页 )

属性值说明:

took – ES 执行搜索的时间 ( 毫秒 )
timed_out – ES 是否超时
_shards – 有多少个分片被搜索了,以及统计了成功/失败/跳过的搜索的分片
max_score – 最高得分
hits.total.value - 命中多少条记录
hits.sort - 结果的排序 key 键,没有则按 score 排序
hits._score - 相关性得分
参考文档:
https://www.elastic.co/guide/en/elasticsearch/reference/current/getting-started-search.html

5.1.2 URL 加请求体进行检索 ( QueryDSL )

请求体中写查询条件

语法:

GET bank/_search

  "query":"match_all": ,
  "sort": [
    "account_number": "asc" 
 ]

示例:查询出所有,先按照 accout_number 升序排序,再按照 balance 降序排序

5.2 详解 QueryDSL 查询

5.2.1 全部匹配 match_all

示例:查询所有记录,按照 balance 降序排序,只返回第 11 条记录到第 20 条记录,只显示 balance 和 firstname 字段。

GET bank/_search

  "query": 
    "match_all": 
  ,
  "sort": [
 
      "balance": 
        "order": "desc"
 
 
  ],
  "from": 10,
  "size": 10,
  "_source": ["balance", "firstname"]

5.2.2 匹配查询 match

  • 基本类型 ( 非字符串 ) ,精确匹配
GET bank/_search

  "query": 
    "match": "account_number": "30"
 
  • 字符串,全文检索
GET bank/_search

  "query": 
    "match": 
      "address": "mill road"
 
 

查到了 32 条记录,最高的一条记录是 Address = "990 Mill Road",得分:8.926605. Address="198 Mill Lane" 评分 5.4032025,只匹配到了 Mill 单词。

5.2.3 短语匹配 match_phase

将需要匹配的值当成一个整体单词 ( 不分词 ) 进行检索

GET bank/_search

  "query": 
    "match_phrase": 
      "address": "mill road"
 
 

5.2.4 多字段匹配 multi_match

GET bank/_search

  "query": 
    "multi_match": 
      "query": "mill land",
      "fields": [
        "state",
        "address"
 ]
 
 

5.2.5 复合查询 bool

搭配使用 must,must_not,should

must: 必须达到 must 指定的条件。 ( 影响相关性得分 )

must_not: 必须不满足 must_not 的条件。 ( 不影响相关性得分 )

should: 如果满足 should 条件,则可以提高得分。如果不满足,也可以查询出记录。 ( 影响相关性得分 )

示例:查询出地址包含 mill,且性别为 M,年龄不等于 28 的记录,且优先展示 firstname 包含 Winnie 的记录。

GET bank/_search

  "query": 
    "bool": 
      "must": [
 
          "match": 
            "address": "mill"
 
        ,
 
          "match": 
            "gender": "M"
 
 
      ],
      "must_not": [
 
          "match": 
            "age": "28"
 
 
      ],
      "should": [
 
          "match": 
            "firstname": "Winnie"
 
 
 ]
 
 

5.2.6 filter 过滤

GET bank/_search

  "query": 
    "bool": 
      "filter": [
 
          "range": 
            "age": 
              "gte":18,
              "lte":40
 
 
 
 ]
 
 

5.2.7 term 查询

非 text 字段精确匹配
GET bank/_search

  "query": 
    "term": 
      "age": "20"
 
 

5.2.8 aggregations 聚合

聚合语法:

"aggregations" : 
    "<聚合名称 1>" : 
        "<聚合类型>" : 
            <聚合体内容>
        
        [,"元数据" :   [<meta_data_body>] ]?
        [,"aggregations" :  [<sub_aggregation>]+ ]?
    
    [,"聚合名称 2>" :  ... ]*
  • 示例 1:搜索 address 中包含 big 的所有人的年龄分布 ( 前 10 条 ) 以及平均年龄,以及平均薪资
GET bank/_search

  "query": 
    "match": 
      "address": "mill"
 
  ,
  "aggs": 
    "ageAggr": 
      "terms": 
        "field": "age",
        "size": 10
       
    ,
    "ageAvg": 
      "avg": 
        "field": "age"
      
    ,
    "balanceAvg": 
      "avg": 
        "field": "balance"
      
   
 

检索结果如下所示:

hits 记录返回了,三种聚合结果也返回了,平均年龄 34 随,平均薪资 25208.0,品骏年龄分布:38 岁的有 2 个,28 岁的有一个,32 岁的有一个

如果不想返回 hits 结果,可以在最后面设置 size:0

GET bank/_search

  "query": 
    "match": 
      "address": "mill"
 
  ,
  "aggs": 
    "ageAggr": 
      "terms": 
        "field": "age",
        "size": 10
      
    
  ,
  "size": 0
  • 示例 2:按照年龄聚合,并且查询这些年龄段的平均薪资

从结果可以看到 31 岁的有 61 个,平均薪资 28312.9,其他年龄的聚合结果类似。

  • 示例 3:按照年龄分组,然后将分组后的结果按照性别分组,然后查询出这些分组后的平均薪资
GET bank/_search

  "query": 
    "match_all": 
 
  ,
  "aggs": 
    "ageAggr": 
      "terms": 
        "field": "age",
        "size": 10
      ,
      "aggs": 
        "genderAggr": 
          "terms": 
            "field": "gender.keyword",
            "size": 10
          ,
          "aggs": 
            "balanceAvg": 
              "avg": 
                "field": "balance"
          
        
      
    
  
 
  ,
  "size": 0

从结果可以看到 31 岁的有 61 个。其中性别为 M 的 35 个,平均薪资 29565.6,性别为 F 的 26 个,平均薪资 26626.6。其他年龄的聚合结果类似。

5.2.9 Mapping 映射

  • 定义哪些字符串属性应该被看做全文本属性 ( full text fields )
  • 定义哪些属性包含数字,日期或地理位置
  • 定义文档中的所有属性是否都能被索引 ( _all 配置 )
  • 日期的格式
  • 自定义映射规则来执行动态添加属性

Elasticsearch7 去掉 tpye 概念:

关系型数据库中两个数据库表示是独立的,即使他们里面有相同名称的列也不影响使用,但 ES 中不是这样的。elasticsearch 是基于 Lucence 开发的搜索引擎,而 ES 中不同 type 下名称相同的 field 最终在 Lucence 中的处理方式是一样的。

为了区分不同 type 下的同一名称的字段,Lucence 需要处理冲突,导致检索效率下降

ES7.x 版本:URL 中的 type 参数为可选。

ES8.x 版本:不支持 URL 中的 type 参数

所有类型可以参考文档:https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-types.html

  • 查询索引的映射

如查询 my-index 索引的映射

GET /my-index/_mapping
返回结果:

  "my-index" : 
    "mappings" : 
      "properties" : 
        "age" : 
          "type" : "integer"
        ,
        "email" : 
          "type" : "keyword"
        ,
        "employee-id" : 
          "type" : "keyword",
          "index" : false
        ,
        "name" : 
          "type" : "text"
      
    
  
 
  • 创建索引并指定映射

如创建 my-index 索引,有三个字段 age,email,name,指定类型为 interge, keyword, text

PUT /my-index

  "mappings": 
    "properties": 
      "age":  "type": "integer" ,
      "email":  "type": "keyword"  ,
      "name":  "type": "text" 
    
 
返回结果:

  "acknowledged" : true,
  "shards_acknowledged" : true,
  "index" : "my-index"

  • 添加新的字段映射

如在 my-index 索引里面添加 employ-id 字段,指定类型为 keyword

PUT /my-index/_mapping

  "properties": 
    "employee-id": 
      "type": "keyword",
      "index": false
    
 
  • 更新映射
  • 数据迁移

POST _reindex

  "source": 
    "index": "twitter"
  ,
  "dest": 
    "index": "new_twitter"
 

个人网站:www.passjava.cn

以上是关于PassJava 开源项目(二十)之 详解 Elasticsearch 高级检索玩法的主要内容,如果未能解决你的问题,请参考以下文章

PassJava 开源项目(十六):Elasticsearch 简介

PassJava 开源 : Spring Cloud 整合Gateway网关 #私藏项目实操分享#

PassJava 开源 : Spring Cloud 整合 Nacos 配置中心 #私藏项目实操分享#

PassJava 开源 : 整合 OpenFeign实现声明式远程调用 #私藏项目实操分享#

PassJava 开源 : Spring Cloud 整合Gateway网关 #私藏项目实操分享#

PassJava 开源(十三) : Spring Cloud 整合 OSS 对象存储 #私藏项目实操分享#