• elasticSearch学习笔记


    1.基本概念

    Index(索引)

    动词相当于mysql的insert,名词相当于databases

    tyep(类型)

    在Index(索引)中,可以定义一个或者多个类型,类似于Mysql中的Table,每一种类型的数据放在一起。

    在ElasticSearch6.X中,一个index中只能存在一个type,而在ElasticSearch7.X中,type的概念已经被废除了。

    Document(文档)

    保存在某个索引下,某个类型的一个数据,文档是JSON格式,Document就像是Mysql中的某个Table里面的内容

    模型

    正向索引和倒排索引的概念

    正排索引

    正向索引 (forward index) 以文档的ID为关键字,表中记录文档中每个字的位置信息,查找时扫描表中每个文档中字的信息直到找出所有包含查询关键字的文档
    在这里插入图片描述

    倒排索引

    倒排索引以字或词为关键字进行索引,表中关键字所对应的记录表项记录了出现这个字或词的所有文档
    在这里插入图片描述

    2.初步检索

    _cat

    GET /_cat/nodes; ## 查看所有节点
    GET /_cat/health;## 查看es的健康状况
    GET /_cat/master; ##查看主节点
    GET /_cat/indices; ## 查看所有索引
    
    • 1
    • 2
    • 3
    • 4

    索引一个文档

    PUT /索引名/类型名/主键id ## 使用put方式,必须传入主键id,如果存在当前id,为更新操作,否则为新增操作
    POST /索引名/类型名/主键id ##使用post方式,传入主键id可选择,如果当前没有传入id,为新增操作,否则传入id,如果存在当前id,为更新操作,否则为新增操作
    
    • 1
    • 2

    在这里插入图片描述

    查询文档操作

    ## 查询指定id的索引
    GET /索引名/_doc/主键id ##例如:GET /shopping/_doc/1
    ## 查询当前索引下的所有数据
    GET /索引名/_search/ ## 例如:GET /shopping/_search
    
    • 1
    • 2
    • 3
    • 4

    在这里插入图片描述

    乐观锁修改:
    更新携带?if_seq_no=0&if_primary_term=1(PUT请求)

    更新文档操作

    POST /索引名/_update/主键名 
    ## 例如:
    POST /shopping/_update/1
    {
      "doc": {
        "更新字段名":"更新数据",
        .....
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    删除文档操作

    DELETE /索引名/_doc/主键id ## 删除一个文档
    
    • 1

    批量操作

    在这里插入图片描述

    3.高级检索

    两种检索方式:

    • 一个是通过使用REST request URI 发送搜索参数(uri+检索参数)(不推荐)
    GET /shopping/_search/?q=*
    
    • 1
    • 一个是通过REST request body来发送他们(uri+请求体)(推荐)
    GET /shopping/_search
    {
      "query": {
        "match": {
          "username": "admin"
        }
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    DSL操作

    语法格式

    {
    	"操作类型“: "操作规则"
    }
    
    • 1
    • 2
    • 3

    按照字段值关键字查询(match操作)

    GET /索引名/_search
    {
    	"query":{
    		"match":{
    			"字段名":"字段值"
    		}
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    查询所有文档(match_all操作)

    GET /shopping/_search 
    {
      "query": {
        "match_all": {
          
        }
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    完全查询和高亮显示(match_phrase)

    GET /shopping/_search
    {
      "query": {
        "match_phrase": {
          "字段名": "字段显示"
        }
      },
      "highlight": {
        "fields": {
          "字段名": {
            
          }
        }
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    分页查询(操作等级与query相等)

    GET /shopping/_search 
    {
      "query": {
        "match_all": {
          
        }
      },
      "from":"1", ##代表offset,从第一个数据开始
      "size":"2" ## 代表limit,查询多少数据
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    只显示部分字段

    GET /shopping/_search 
    {
      "query": {
        "match_all": {
          
        }
      },
      "_source": ["字段名1", "字段名2"...]
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    排序

    不能对文本类型进行排序

    GET /shopping/_search
    {
      "query": {
        "match_all": {
          
        }
      },
      "sort": [
        {
          "字段名": {
            "order": "升序或者降序(ASC或者DESC)"
          }
        }
      ]
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    多添加查询

    GET /shopping/_search
    {
      "query": {
        "bool": {
          "must": [  ## must中的条件必须同时符合,类似于and
            {
              "match": {
                "price": "3"
              }
            }
          ],
          "should": [ ## should中的条件符合其一集合,类似于or
            {
              "match": {
                "username.keyword": "admin"
              }
            }
          ],
          "filter": { ##过滤以上结果
            "range": { ## 范围过滤
              "price": {
                "gte": 1,
                "lte": 5
              }
            }
          }
        }
      }
    }
    
    • 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

    聚合操作(aggs)

    GET /bank/_search
    {
      "query": {
        "match_all": {}
      },
      "aggs": {
        "age_group": { ##聚合操作名
          "terms": { ## 聚合操作类型
            "field": "age"
            "size": 10
          }
        }
      },
      "size": 0
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    映射(mapping)

    表示字段的类型,一般在创建索引的时候指定,但是在ElasticSearch8中,将移除,因此,此处降只记录一个概念。
    创建一个映射

    PUT /testIndex
    {
      "mappings": {
        "properties": {
          "age": {
            "type":"integer", ## 字段类型
            "index": false, ## 是否能够被索引到
            "doc_values": true ##是否存储到磁盘中
          },
          "email": {
            "type":"keyword" ## 字段类型
          }
        }
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    在已创建的映射中添加一个字段映射

    PUT /testIndex/_mapping
    {
      "properties": {
        "email": {
            "type":"keyword" ## 字段类型
          }
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    修改已存在字段的类型

    elasticsearch中不能修改已存在字段的类型,因为这样会使历史数据丢失,因此在elasticsearch中如果要修改现有字段的类型,只能创建一个新的索引,规定mapping后,进行数据迁移、

    数据迁移
    elasticsearch6.0之后的写法
    在这里插入图片描述
    elasticsearch6.0以前的写法
    在这里插入图片描述
    在这里插入图片描述

    分词

    一个tokenizer(分词器)接受一个字符流,将之分隔为独立的tokens(词元,通常是独立的单词),然后输出tokens流。
    ElasticSearch提供了很多内置的分词器,可以用来构建custom analyzers(自定义分词器)

    安装ik分词器

    下载地址:https://hub.fastgit.xyz/medcl/elasticsearch-analysis-ik/releases?page=7
    安装步骤
    将插件安装包传入elasticsearch的plugin目录下,即可。

    自定义分词器

    配置文件地址:elasticsearch/plugins/ik/config/IKAnalyzer.cfg.xml,由于配置的分词器是对应的网络地址,因此,我们需要搭一个Nginx。
    在这里插入图片描述

    搭建nginx

    docker-compose内容:

     nginx:
        image: nginx
        container_name: nginx
        ports:
          - "8000:80"
        volumes:
          - './nginx/html:/usr/share/nginx/html'
          - './nginx/logs/:/var/log/nginx/'
          - './nginx/conf/:/etc/nginx/'
        restart: always
        privileged: true
        networks:
          - rmq1
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    将nginx的容器复制到外面

    docker container cp nginx:/etc/nginx ./nginx_1
    
    • 1

    在nginx/html/目录下创建一个txt文件,添加你的词组
    将对应的访问路径放入elasticsearch文件即可。

    4.SpringBoot集成ElasticSearch

    单体架构

    使用步骤:

    1.加入jar包

    <dependency>
       <groupId>org.springframework.bootgroupId>
       <artifactId>spring-boot-starter-data-elasticsearchartifactId>
    dependency>
    
    • 1
    • 2
    • 3
    • 4

    2.application.yaml中加入配置

    spring:
      elasticsearch:
        rest:
          uris:
            - IP地址:端口
    
    • 1
    • 2
    • 3
    • 4
    • 5

    3.工具类:ElasticsearchRestTemplate(是使用 High Level REST Client 的 ElasticsearchOperations 接口的实现)
    4.创建实体类

    package com.tom.gulimall.search.es;
    
    import com.tom.common.es.AttrsEsModelDto;
    import org.springframework.data.annotation.Id;
    import org.springframework.data.elasticsearch.annotations.Document;
    import org.springframework.data.elasticsearch.annotations.Field;
    import org.springframework.data.elasticsearch.annotations.FieldType;
    import org.springframework.data.elasticsearch.annotations.IndexPrefixes;
    
    import java.util.List;
    
    /**
     * @author: wys
     * @date: 2022/9/8 17:42
     * @description: 首页索引
     */
    
    @Document(indexName = "product") //设置索引名,如果不存在,默认创建
    @Data
    public class HomeIndexEntity {
    
        @Id
        @Field(type = FieldType.Long)
        private Long skuId;
    
        @Field(type = FieldType.Keyword)
        private Long spuId;
    
        @Field(type = FieldType.Text, analyzer = "ik_smart")
        private String skuTitle;
    
        @Field(type = FieldType.Keyword)
        private String skuPrice;
    
        @Field(type = FieldType.Keyword, index = false, docValues = false)//index代表不作为索引对象,docValue表示不序列化
        private String skuImg;
    
        @Field(type = FieldType.Long)
        private Long saleCount;
    
        @Field(type = FieldType.Boolean)
        private Boolean hasStock;
    
        @Field(type = FieldType.Long)
        private Long hotScore;
    
        @Field(type = FieldType.Long)
        private Long brandId;
    
        @Field(type = FieldType.Long)
        private Long catelogId;
    
        @Field(type = FieldType.Keyword, index = false, docValues = false)
        private Long brandName;
    
        @Field(type = FieldType.Keyword, index = false, docValues = false)
        private String brandImg;
    
        @Field(type = FieldType.Keyword, index = false, docValues = false)
        private String catelogName;
    
        @Field(type = FieldType.Object)
        private List<AttrsEsModelDto> attr;
    }
    
    • 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

    5.创建持久层对象,继承ElasticsearchRepository接口

    //第一个泛型代表操作对象,第二个泛型代表主键id类型
    @Component
    public interface UpProductDao extends ElasticsearchRepository<HomeIndexEntity, Long> {
    
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    6.可以根据语法定义常用方法,也可以用@Query自定义方法

    GET /product/_search
    {
      "query": {
        "match_all": {}
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    上述查询方法,可以简述为(@Query中的内容为【“query”:】后的内容):

    @Query("{\n" +
                "    \"match_all\": {}\n" +
                "  }")
    List<HomeIndexEntity> findAllProduct();
    
    • 1
    • 2
    • 3
    • 4

    5.常见的问题:

    ES存储数组数据的时候会对数据执行扁平化操作,而扁平化操作会导致数据操作错误,如何解决这种影响?

    设置属性为nested类型
    在这里插入图片描述

  • 相关阅读:
    pubsub消息订阅与发布
    C++类和对象(中)【万字详解】
    curl 和 wget 的使用和区别
    机器学习笔记 - CRAFT(文本检测的字符区域感知)论文解读
    java17 linux 环境配置
    第五章 数据库设计和事务 ② 代码
    遇到一个异步任务后是否会直接加入到异步队列当中
    linux gdb运行不下去的程序调试方法
    基础语言-第18天-csv、Excel文件操作
    leetcode:20. 有效的括号
  • 原文地址:https://blog.csdn.net/m0_46486963/article/details/126482126