type
status
date
slug
summary
tags
category
icon
password
URL
文章来源说明

全文检索

全文检索是一种通过对文本内容进行全面索引和搜索的技术。它可以快速地在大量文本数据中查找包含特定关键词或短语的文档,并返回相关的搜索结果
 
es搜索原理:将文档通过分词器进行分词处理,然后记录每个单词在哪些文档中出现,和出现的位置。而查询时可以通过关键语句来快速定位到这些文档。
 

分词插件安装

分词插件决定了文档会被分词成哪些

IK中文分词器

本地下载elasticsearch-analysis-ik-7.17.3.zip插件,解压,然后手动上传到elasticsearch的plugins目录,然后重启ES实例就可以了。
 
 

索引:index

索引在 ES 中所表述的含义和 MySQL 中的索引完全不同,在 MySQL 中索引指的是加速数据查询的一种特殊的数据结构,如 normal index。 而在 ES 中,索引表述的含义等价于 MySQL 中的表(仅针对 ES 7.x 以后版本),注意这里只是类比去理解,索引并不等于表。
 
在 ES 中,索引在不同的特定条件下可以表示三种不同的意思:
  • 表示源文件数据:当做数据的载体,即类比为数据表,通常称作 index 。例如:通常说 集群中有 product 索引,即表述当前 ES 的服务中存储了 product 这样一张“表”。
  • 表示索引文件:以加速查询检索为目的而设计和创建的数据文件,通常承载于某些特定的数据结构,如哈希、FST 等。例如:通常所说的 正排索引 和 倒排索引(也叫正向索引和反向索引)。就是当前这个表述,索引文件和源数据是完全独立的,索引文件存在的目的仅仅是为了加快数据的检索,不会对源数据造成任何影响,
  • 表示创建数据的动作:通常说创建或添加一条数据,在 ES 的表述为索引一条数据或索引一条文档,或者 index 一个 doc 进去。此时索引一条文档的含义为向索引中添加数据。
 
索引的组成部分:
  • alias:索引别名
  • settings:索引设置,常见设置如分片和副本的数量等。
  • mapping:映射,定义了索引中包含哪些字段,以及字段的类型、长度、分词器等。
notion image
 

类型:Type(ES 7.x 之后版本已删除此概念)

在较早的ES版本中,索引可以包含多个类型,每个类型代表了不同的文档结构。然而,从ES 7.x版本开始,类型已经被弃用,一个索引只能包含一个文档类型。
ES 7.x
  • 不推荐在请求中指定类型。例如,索引文档不再需要文档type。新的索引 API 适用PUT {index}/_doc/{id}于显式 ID 和POST {index}/_doc 自动生成的 ID。请注意,在 7.0 中,_doc是路径的永久部分,表示端点名称而不是文档类型。
  • 索引创建、索引模板和映射 API 中的include_type_name参数将默认为false. 完全设置参数将导致弃用警告。
  • _default_映射类型被删除 。
ES 8.x
  • 不再支持在请求中指定类型。
  • 该include_type_name参数被删除。
 

文档:Document

文档是ES中的最小数据单元。它是一个具有结构化JSON格式的记录。文档可以被索引并进行搜索、更新和删除操作。
notion image
 
  • _index:文档所属的索引名
  • _type:文档所属的类型名
  • _id:文档唯一id
  • _source: 文档的原始Json数据
  • _version: 文档的版本号,修改删除操作_version都会自增1
  • _seq_no: 和_version一样,一旦数据发生更改,数据也一直是累计的。Shard级别严格递增,保证后写入的Doc的_seq_no大于先写入的Doc的_seq_no。
  • _primary_term: _primary_term主要是用来恢复数据时处理当多个文档的_seq_no一样时的冲突,避免Primary Shard上的写入被覆盖。每当Primary Shard发生重新分配时,比如重启,Primary选举等,_primary_term会递增1。
 

ElasticSearch索引操作

创建索引

格式: PUT /索引名称
索引命名规范:
  • 以小写英文字母命名索引
  • 不要使用驼峰命名法则
  • 如过出现多个单词的索引名称,以全小写 + 下划线分隔的方式:如test_index。
ES 索引创建成功之后,以下属性将不可修改
  • 索引名称
  • 主分片数量
  • 字段类型
 
 
notion image
 
 

查询索引

格式: GET /索引名称
 
notion image
 

删除索引

格式: DELETE /索引名称
 

设置Settings

创建索引的时候指定 settings
 
创建索引时可以设置分片数和副本数
 
创建索引时可以指定IK分词器作为默认分词器
 

设置文档映射Mapping

ES 中的 mapping 有点类似与关系数据库中表结构的概念,在 MySQL 中,表结构里包含了字段名称,字段的类型还有索引信息等。在 Mapping 里也包含了一些属性,比如字段名称、类型、字段使用的分词器、是否评分、是否创建索引等属性,并且在 ES 中一个字段可以有多个类型。ES中Mapping可以分为动态映射和静态映射。
 
 
mapping 的使用禁忌
  • ES 没有隐式类型转换
  • ES 不支持类型修改
  • 生产环境尽可能的避免使用 动态映射(dynamic mapping)
 

动态映射

在关系数据库中,需要事先创建数据库,然后在该数据库下创建数据表,并创建表字段、类型、长度、主键等,最后才能基于表插入数据。而Elasticsearch中不需要定义Mapping映射,在文档写入Elasticsearch时,会根据文档字段自动识别类型,这种机制称之为动态映射。
自动类型推断规则
 
notion image
 
例子
 
notion image
 
 

静态映射

静态映射也叫做显式映射,即:在索引文档写入之前,人为创建索引并且指定索引中每个字段类型、分词器等参数。
 
参数名称
释义
analyzer
指定分析器,只有 text 类型字段支持。
copy_to
该参数允许将多个字段的值复制到组字段中,然后可以将其作为单个字段进行查询
dynamic
控制是否可以动态添加新字段,支持以下四个选项:true:(默认)允许动态映射false:忽略新字段。这些字段不会被索引或搜索,但仍会出现在_source返回的命中字段中。这些字段不会添加到映射中,必须显式添加新字段。runtime:新字段作为运行时字段添加到索引中,这些字段没有索引,是_source在查询时加载的。strict:如果检测到新字段,则会抛出异常并拒绝文档。必须将新字段显式添加到映射中。
doc_values
为了提升排序和聚合效率,默认true,如果确定不需要对字段进行排序或聚合,也不需要通过脚本访问字段值,则可以禁用doc值以节省磁盘空间(不支持 text 和 annotated_text)
eager_global_ordinals
用于聚合的字段上,优化聚合性能。
enabled
是否创建倒排索引,可以对字段操作,也可以对索引操作,如果不创建索引,任然可以检索并在_source元数据中展示,谨慎使用,该状态无法修改。
fielddata
查询时内存数据结构,在首次用当前字段聚合、排序或者在脚本中使用时,需要字段为fielddata数据结构,并且创建倒排索引保存到堆中
fields
给 field 创建多字段,用于不同目的(全文检索或者聚合分析排序)
format
用于格式化代码,如"data":{ "type": "data", "format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis" }
index
是否对创建对当前字段创建倒排索引,默认 true,如果不创建索引,该字段不会通过索引被搜索到,但是仍然会在 source 元数据中展示。
norms
是否禁用评分(在filter和聚合字段上应该禁用)
null_value
为 null 值设置默认值
search_analyzer
设置单独的查询时分析器
示例:
  • index: 控制当前字段是否被索引,默认为true。如果设置为false,该字段不可被搜索
 
 
notion image
 
• dynamic设为true时,一旦有新增字段的文档写入,Mapping 也同时被更新;dynamic设置成strict(严格控制策略),文档写入失败,抛出异常
注意:对已有字段,一旦已经有数据写入,就不再支持修改字段定义
  • Lucene 实现的倒排索引,一旦生成后,就不允许修改
  • 如果希望改变字段类型,可以利用 reindex API,重建索引
 

使用ReIndex重建索引

具体方法:
1)如果要推倒现有的映射, 你得重新建立一个静态索引
2)然后把之前索引里的数据导入到新的索引里
3)删除原创建的索引
4)为新索引起个别名, 为原索引名
通过这几个步骤可以实现了索引的平滑过渡,并且是零停机
 
 

ElasticSearch文档操作

数据准备
 

索引文档

• 格式: [PUT | POST] /索引名称/[_doc | _create ]/id
 
 
注意:POST和PUT都能起到创建/更新的作用,PUT需要对一个具体的资源进行操作也就是要确定id才能进行更新/创建,而POST是可以针对整个资源集合进行操作的,如果不写id就由ES生成一个唯一id进行创建新文档,如果填了id那就针对这个id的文档进行创建/更新
notion image
 
notion image
 

查询文档

• 根据id查询文档,格式: GET /索引名称/_doc/id
 
• 条件查询 _search,格式: /索引名称/_doc/_search
ES Search API提供了两种条件查询搜索方式:
  • REST风格的请求URI,直接将参数带过去
  • 封装到request body中,这种方式可以定义更加易读的JSON格式
 

URI Query(了解即可)

DSL Query

DSL(Domain Specific Language领域专用语言)查询是使用Elasticsearch的查询语言来构建查询的方式。
 
例子
 
 

修改文档

• 全量更新,整个json都会替换,格式: [PUT | POST] /索引名称/_doc/id
如果文档存在,现有文档会被删除,新的文档会被索引
 
notion image
 
• 使用_update部分更新,格式: POST /索引名称/_update/id
update不会删除原来的文档,而是实现真正的数据更新
 
notion image
 
• 使用 _update_by_query 更新文档
 
notion image
 

并发修改文档

_seq_no和_primary_term是对_version的优化,7.X版本的ES默认使用这种方式控制版本,所以当在高并发环境下使用乐观锁机制修改文档时,要带上当前文档的_seq_no和_primary_term进行更新:
如果版本号不对,会抛出版本冲突异常,如下图:
notion image
 
删除文档
格式: DELETE /索引名称/_doc/id
 

文档批量操作

批量操作可以减少网络连接所产生的开销,提升性能
  • 支持在一次API调用中,对不同的索引进行操作
  • 可以在URI中指定Index,也可以在请求的Payload中进行
  • 操作中单条操作失败,并不会影响其他操作
  • 返回结果包括了每一条操作执行的结果
 

批量写入

批量对文档进行写操作是通过_bulk的API来实现的
  • 请求方式:POST
  • 请求地址:_bulk
  • 请求参数:通过_bulk操作文档,一般至少有两行参数(或偶数行参数)
  • 第一行参数为指定操作的类型及操作的对象(index,type和id)
  • 第二行参数才是操作的数据
• actionName:表示操作类型,主要有create,index,delete和update
 

springboot整合ElasticSearch

版本选择
Elasticsearch 7.17.3 对应依赖 Spring Data Elasticsearch 4.4.x,对应springboot版本2.7.x
 
notion image
 
 
引入依赖
 

yml配置

 

创建实体

 

实现ElasticsearchRepository

该接口是框架封装的用于操作Elastsearch的高级接口
测试
 

使用ElasticsearchRestTemplate

ElasticsearchRestTemplate模板类,封装了便捷操作Elasticsearch的模板方法,包括 索引 / 映射 / CRUD 等底层操作和高级操作。
 
索引操作
 
文档操作
 
 

项目使用

notion image
针对商品进行搜索

ES索引结构

创建索引库

 
简单分析
  1. "id"、"name"、"keywords"、"subTitle"、"salecount"、"putawayDate"、"price" 等字段:这些字段定义了索引中的数据列,每个字段都有指定的数据类型。例如,"id" 是长整型,"name"、"keywords"、"subTitle" 使用了 "ik_max_word" 分词器,用于全文搜索的文本字段。
  1. "promotionPrice"、"originalPrice"、"pic" 等字段:这些字段使用 "keyword" 数据类型,通常用于不需要分析的精确匹配字段,如关键字或标识符。
  1. "brandId"、"brandName"、"brandImg"、"categoryId"、"categoryName" 等字段:这些字段包含品牌和类别相关的信息,使用了 "keyword" 或 "long" 数据类型。
  1. "attrs":这是一个嵌套字段,包含了属性的信息,每个属性都有 "attrId"、"attrName"、"attrValue" 这些子字段,用于存储属性的详细信息。
 
索引数据准备
 
检索DSL语句构建
 
 
postman测试
 
DSL语句简单分析
这个DSL(领域特定语言)语句是用于在名为 "product_db" 的索引中执行搜索和聚合操作的请求。以下是对该DSL语句的逐步解释:
  1. POST /product_db/_doc/_search:这是一个HTTP POST请求,用于在 "product_db" 索引的 "_doc" 类型上执行搜索操作。
  1. "from": 0"size": 8:这些参数指定了搜索结果的分页。从第0个结果开始(即第一个结果),并返回8个结果。
  1. "query":这是查询部分的开始。
      • "bool":这是布尔查询,允许同时使用多个查询子句。
        • "must":这是必须匹配的查询子句。
          • "match":这是一个全文搜索查询,用于匹配 "name" 字段中包含 "手机" 的文档。
        • "filter":这是过滤查询子句,用于过滤结果。
          • "term":这是一个精确匹配查询,用于匹配 "hasStock" 字段为 "true" 的文档。
          • "range":这是一个范围查询,用于匹配 "price" 字段在1到5000之间的文档。
  1. "sort":这是排序参数,指定了按照 "salecount" 字段升序排序搜索结果。
  1. "aggregations":这是聚合操作的开始,用于生成分析数据。
      • "brand_agg":这是一个品牌聚合,按照 "brandId" 字段分组,最多返回50个结果。
        • "brand_name_agg":在品牌聚合内部,按照 "brandName" 字段分组。
        • "brand_img_agg":在品牌聚合内部,按照 "brandImg" 字段分组。
      • "category_agg":这是一个类别聚合,按照 "categoryId" 字段分组,最多返回50个结果,至少有一个文档匹配。
        • "category_name_agg":在类别聚合内部,按照 "categoryName" 字段分组。
      • "attr_agg":这是一个属性聚合,涉及嵌套字段 "attrs"。
        • "attr_id_agg":在属性聚合内部,按照 "attrs.attrId" 字段分组。
          • "attr_name_agg":在属性聚合内部,按照 "attrs.attrName" 字段分组。
          • "attr_value_agg":在属性聚合内部,按照 "attrs.attrValue" 字段分组。
  1. "highlight":这是高亮部分的定义,用于将匹配查询的 "name" 字段的文本标记为红色。
总之,这个DSL语句执行了一个搜索操作,查找包含特定关键字("手机")的商品,价格在1到5000之间,并且库存充足的商品。同时,它还生成了品牌、类别和属性的聚合数据,以及高亮显示匹配的商品名称。
 
对应sql如下
 

重点

代码实现

 
 
 
 
致谢:
💡
有关Notion安装或者使用上的问题,欢迎您在底部评论区留言,一起交流~
 
 
统一异常处理分布式锁
Loading...