• 要理解倒排索引
  • 要能够使用DSL命令操作索引库
  • 要能够使用DSL命令操作文档
  • 要能够使用RestAPI操作索引库、文档

一、ES简介

  • 理解倒排索引的概念和作用
  • 理解es和MySql的区别和使用场景

1. 数据库查询的问题

假如我们有一个电商系统,需要查询商品。以前一直是直接从MySql数据库里用SQL语句模糊查询,例如:select * from tb_product where pname like '%华为手机%'

但是这种查询检索数据的方式,有很大的问题:

  • 查询性能很低

    MySql可以通过索引的方式来提高查询的效率,但是像上边这种模糊查询以%开头,会导致索引失效,实际上执行的是全表扫描,效率非常低。

  • 查询结果不准确

    我们应当查询到与“手机”、“华为”等词条相关的所有商品,而不是 只包含“华为手机”的商品

 而这些问题,都可以使用ElasticSearch轻易的解决掉:把数据存储到ElasticSearch里,由ElasticSearch提供高效的文档检索能力

2. ES简介

2.1 ElasticSearch简介

ElasticSearch,简称ES。

ES是:一款非常强大的开源搜索引擎,可以帮助我们从海量数据中快速找到需要的内容

如:百度搜索、京东商品搜索、打车软件中搜附近的车辆等等。

ES结合kibana、Logstash、Beats(也就是ELK技术栈,Elastic Stack),

被广泛的用户在日志数据分析、实时监控等领域。

ES是:ELK的核心,负责存储、搜索、分析数据

2.2 ElasticSearch发展

  • Doug Cutting于1999年研发了一个Java语言的搜索引擎类库(函数库):Lucene,目前已是Apache的顶级项目。

    官网地址:Apache Lucene - Welcome to Apache Lucene

    Lucene优势:易扩展、高性能(基于倒排索引)

    Lucene缺点:只限于Java语言、学习曲线陡峭、不支持水平扩展

  • 2004年Shay Banon基于Lucene开发了Compass,随后于2010年重写了Compass,取名为ElasticSearch。

    官网地址:欢迎来到 Elastic — Elasticsearch 和 Kibana 的开发者 | Elastic

    相比于Lucene,ElasticSearch具备更多优势:

    1. 支持分布式,可水平扩展

    2. 提供RESTful接口,任何编程语言都可以使用。

  • 到目前为止,ElasticSearch已经成为主流的搜索引擎

3. 倒排索引

3.0 索引介绍

索引:索引是一种数组结构,可以帮助我们快速查找数据,提升查询的速度。类似于字典的目录

  • 如果没有目录:想要查找一项数据,就需要全表扫描,速度非常慢

  • 可以构造目录:

  • 根据拼音构造了目录:想要查找一个字,就可以根据拼音,从拼音目录里快速找到这个字在哪一页

直接到这一页,获取这个字的详细信息了

  • 根据笔画构造了目录:想要查找一个字,就可以根据笔画,从笔画目录里快速找到这个字在哪一页

直接到这一页,获取这个字的详细信息了

  • 根据偏旁构造了目录:想要查找一个字,就可以根据偏旁,从偏旁目录里快速找到这个字在哪一页

直接到这一页,获取这个字的详细信息了

在数据库里:

  • 如果没有索引:想要查找一条数据,就需要全表扫描,速度非常慢

  • 可以构造索引:

  • 根据主键id构造索引:想要查找id为1的数据,直接去索引里找到id对应的数据在磁盘上哪个地址

直接跳转到这个地址,获取这条数据的详细信息

  • 根据用户名构造索引:想要查找“张三”数据,直接去用户名索引里找到数据对应的地址

直接到这个地址,获取这条数据的详细信息

索引的特点:

  • 可以极大的提升查询速度

  • 但是会影响增删改的速度

3.1 正向索引

说明

传统RDBMS(例如MySql)采用的是正向索引,

即:根据表的主键字段构建索引,在查询时要扫描到每个索引值对应的数据,

从中筛选出符合查询条件的记录。

这样的检索方式构建索引简单,但是不适合复杂的文档检索。

复杂的文档检索时,索引会失效,变成全表扫描

示例

以商品表搜索为例,商品表tb_product如下:

id title price
1 小米手机 3499
2 华为手机 4999
3 华为小米手机充电器 49
4 小米手环 79

要搜索包含“手机”的商品,执行SQL:select * from tb_product where title like '%手机%'

MySql会扫描所有的数据记录逐条判断 “title”的值是否包含“手机”,直到全表扫描,过滤出所有符合要求的结果

3.2 倒排索引

说明

ElasticSearch采用的是倒排索引

即:以关键字构建索引,保存每个关键字所在的记录。

需要查询时,根据词条匹配查询条件,直接找到关联的记录。

倒排索引建立和维护都比较复杂,但是在查询时可以和查询关键字关联的所有结果并快速响应。

示例

以商品表搜索为例,商品表略

构建倒排索引

词条(term) 文档id
小米 1, 3, 4
手机 1, 2
华为 2, 3
充电器 3
手环 4

文档Document每条数据就是一个文档

词条term按照语义分成的词语

当搜索“华为手机”时:

  1. 搜索条件进行分词,得到两个词条“华为”, “手机”

  2. 根据词条去倒排索引里查询相关的文档id,得到:

    • “华为”:2, 3

    • “手机”:1, 2

  3. 根据文档id,找到对应的文档数据,得到:id为1、2、3的文档

4. ES和MySql

使用方式

传统的RDBMS和ElasticSearch各有所长:

RDBMS是 Relational Database Management System 的缩写,

中文译为“关系数据库管理系统

它是 SQL 语言以及所有现代数据库系统(例如 SQL Server、DB2、Oracle、MySQL 和 Microsoft Access)的基础。
关系数据库管理系统(RDBMS)是一种基于 E. F. Codd 发明的关系模型的数据库管理系统(DBMS)。

  • MySQL:擅长事务类操作,可以确保数据的一致性和安全性

  • ES:擅长海量数据的搜索、分析、计算

在实际开发中,通常是结合使用

  • MySQL负责写操作

  • ES负责搜索操作

5. 小结

正向索引:先找到数据,再判断数据是否符合条件。需要全表扫描,速度慢
倒排索引:根据词条去倒排索引里找文档id,直接找到数据。不需要全表扫描,速度极快
    1. ES会对数据表里的某些字段构建倒排索引
        对这个字段的值,进行拆词(分词),得到词条
        构建出来 每个词条 与 文档id的对应关系
        这个对应关系,就是倒排索引
    2. 在搜索数据时,提供搜索词
        ES会对搜索词进行拆词(分词)得到词条
        去倒排索引里,直接找到关联的文档id,获取id对应的数据
ES和MySQL的使用方式
    有查询操作,找ES
    有增删改操作,找MySQL
    然后MySQL和ES之间要实现数据同步

二、安装ES

掌握

  • 安装es7.4,安装kibana
  • 安装ik分词器
  • 理解ik分词器的分类和作用

1. 安装ES

目前我们安装的是ES的7.4.0版本,需要JDK8及以上

1.1 解压

把《elasticsearch-7.4.0-windows-x86_64.zip》解压到一个不含中文、空格、特殊字符的目录里

1.2 配置

1) 配置存储路径

打开config/elasticsearch.yml文件,设置索引数据的存储路径,和日志的存储路径

2) 配置虚拟机参数

进入es的bin目录,直接双击 elasticsearch.bat即可启动

es服务要占用两个端口:

  • 9200:rest访问接口,我们稍后要通过这个端口连接es、操作es

  • 9300:用于es集群间通信的接口

1.3 验证

在浏览器上直接输入地址 http://localhost:9200/, 如果看到以下界面,说明es启动成功了

2. 安装Kibana

Kibana是一个ES索引库数据统计工具,可以利用ES的聚合功能,生成各种图表,如柱形图,线状图,饼图等。

而且还提供了操作ES索引数据的控制台,并且提供了一定的API提示,非常有利于我们学习ES的语法。

2.1 安装nodeJs

Kibana依赖于nodeJs,需要在windows下先安装Node.js,然后才能安装Kibana。

双击nodejs的安装包,按照提示一步步安装即可

安装成功后,打开cmd 输入:node -v,如果能看到版本号,说明node安装成功

2.2 安装Kibana

1) 解压

把《kibana-7.4.0-windows-x86_64.zip》解压到不含中文、空格、特殊字符的目录里

2) 配置

修改kibana的config/kibana.yml,配置es的地址

3) 启动

进入到kibana的bin目录,双击 kibana.bat 启动。启动稍微有些慢,耐心等待一会

4) 访问

打开浏览器输入 http://localhost:5601/

3. 安装IK分词器

3.1 ES标准分词器的问题

ES自带的分词器叫“Standard Analyzer”,它对中文的支持非常不友好,会将一个词语的每个字拆分成一个词条,和中文的语法是完全不符的。

例如,一个词语“使用分词器”,按中文语法习惯可以拆分成“使用”,“分词器”,“分词”等词条。但是标准分词器分拆分成“使”,“用”,“分”,“词”,“器”

示例如下:

 3.2 安装IK分词器   结果焕然一新

为了解决中文词语拆分的问题,可以安装一个IK分词器。IK分词器是一款适合于中文分词习惯的、优秀的中文分词器,具有60万字/秒的高速处理能力。

它支持两种粒度的拆分:

  • ik_smart:粗粒度的拆分

  • ik_max_word:将文本做细粒度的拆分,拆分出尽可能多的词条

1) 解压  自己实操一下

把分词器《elasticsearch-analysis-ik-7.4.0.zip》解压到es的plugins目录下,重命名为“ik”

2) 重启

  1. 重启es

  2. 重启kibana

3) 测试

在浏览器的kibana开发工具界面,输入并执行

4.使用Postman测试

路径:http://localhost:9200/_analyze

内容:可以先测试一下正常了再自己实操练习

{"text":"2023年5月17号,演示一下postman请求ES,首先在ES里面plugins文件夹里面创建一个文件夹比如“ik”,然后在ik文件夹里面解压ik分词器即可!最后按照如图的格式请求postman请求ES即可","analyzer":"ik_smart"
}

5. 安装过程中可能出现的问题

5.1 JDK环境变量问题

ElasticSearch7.4,要求使用jdk8或者jdk11。如果JDK版本不正确,启动es会报错

验证方式:打开cmd,执行java -version,看一下JDK版本

5.2 端口占用问题

苍穹外卖里内网穿透软件cpolar,占用的是9200端口,会导致使用es出问题

解决方式:

  • 方式一:关掉cpolar或者卸载cpolar,然后重启电脑,再启动es,就没有端口冲突了。es会占用9200端口

  • 方式二:不管它,es发现9200被占用,它会自动改用其它端口。要看一下启动es的控制台,看它的端口是多少 (一般是9201)。

    然后Kibana要配置连接ES时的地址,配置成 http://localhost:9201

5.3 操作系统权限问题

你的电脑当前用户权限不足,会导致启动es和Kibana会报错 “operate ... prom...”。解决方法是:

es文件夹和Kibana文件夹都需要设置:

  • 在文件夹上右键-属性-安全-编辑-添加

  • 在弹出的容器里,添加当前计算机用户名(可以在cmd里使用 net user 查看)

  • 勾选中这个用户,点击下边的“完全控制”,再确定

三、操作索引

  • 理解es的核心概念
  • 掌握索引库的CURD

1. ES的核心概念

  • 老版本(es7之前)结构:

Indices----->Type---->document----->field

Database-->Table--->row-------------->column

  • 从es7开始,抛弃了type的概念:

Index(索引库)-->Document(json文档)-->Field(json里的key)

Table------------->Row------------------------->column

MySQL ES 说明
Table Index 索引Index,就是文档的集合,类似数据库表。注意:索引名必须小写
Row Document

文档Document,就是一条数据,类似于数据库表中一行记录。

文档是json格式

Column Field 字段Field,json中的字段,类似于数据库中的列column
Schema Mapping

映射Mapping,索引中文档的约束,例如字段类型约束。

类似于数据库的表结构

SQL DSL DSL是ES提供的json格式请求语句,用来操作ES,实现CURD

2. 操作索引库

2.1 索引库映射mapping

说明

映射mapping:目的是为了给索引的每个Field设置类型(字符串,数字,日期,对象,数组……)

在MySql里,我们在插入一条记录之前,需要提前设置好表里每个每个字段的类型。

而类似的,在ES里,我们需要给每个索引库设置映射信息

参考:Put mapping API | Elasticsearch Guide [7.4] | Elastic

映射类型

常见的mapping属性有:

  • type:字段的类型,常见的简单类型

    • text:可分词文本字符串如果是text需要设置analyzer分词器

    • keyword:不分词文本字符串某些字符串一旦分词失去意义了,例如品牌、国家、ip地址

    • byte,short,integer,long,double,float等数值

    • boolean

    • date日期。ES可以把日期格式化字符串存储,但是为了节省空间,建议使用long存储毫秒值

    • object对象。如果是object,需要设置properties

  • index:是否创建索引默认true。如果字段值不参与搜索,要设置为false。比如图片url

  • analyzer:使用哪种分词器text类型需要设置,其它类型的字段不需要设置

  • properties:字段的子字段。如果字段是object时,需要设置子字段

示例

有如下文档数据,分析该索引库的mapping映射

{"age": 21,  #type是integer"weight": 52.1, #type是double"isMarried": false, #type是boolean"info": "ES搜索引擎操作索引", #type是text,analyzer可用ik_smart"email": "zyyny@itcast.cn", #type是keyword"score": [99.1, 99.5, 98.9], #type是double"name": { #type是object"firstName": "云","lastName": "赵"}
}#索引库的结构
{"mappings":{"properties":{"age":{"type": "integer"},"weight":{"type": "double","index": false},"isMarrid":{"type": "boolean"},"info":{"type": "text","analyzer": "ik_smart"},"email":{"type": "keyword"},"score":{"type": "double"},"name":{"type": "object","properties":{"firstName":{"type": "keyword"},"lastName":{"type": "keyword"}}}}}
}
{"mappings":{"properties":{"id":{"type": "long"},"title":{"type": "text","analyzer": "ik_smart"},"price":{"type": "double"},"picUrl":{"type": "keyword","index": false}}}
}

2.2 索引库的CURD

2.2.1 创建索引库

语法

PUT /索引库名
{"mappings":{"properties":{"字段名":{"type": "类型","index": true,"analyzer": "分词器",...},"字段名":{"type": "类型","index": true,"analyzer": "分词器",...},...}}
}

示例

#--------如何操作索引库---------
#1.创建索引库
PUT /suoyinku
{"mappings": {"properties": {"id":{"type":"integer"},"name":{"type":"text","analyzer": "ik_max_word"},"sex":{"type":"keyword"},"age":{"type":"integer"},"score":{"type":"double"},"avatar":{"type": "keyword","index": false}}}
}
#2.查询所有索引库
GET /_cat/indices#3.查看库详细信息
GET /suoyinku#4.修改索引库
# 不允许修改已有字段,只能新增字段
PUT /suoyinku/_mapping
{"properties":{"email":{"type":"keyword"}}
}#5.删除索引库
DELETE /suoyinku
#-------------------------------------------------------------------------#   练习,创建索引库itcast。四个字段 商品名称title,商品图片images,商品价格price,品牌brand
PUT /itcast
{"mappings": {"properties": {"title":{"type": "text","analyzer": "ik_smart"},"images":{"type": "keyword","index": false},"price":{"type": "double"},"brand":{"type": "keyword"}}}
}

2.2.2 查看索引库

语法

GET /索引库名
#2.查询所有索引库
GET /_cat/indices
#3.查看库详细信息
GET /suoyinku

2.2.3 修改索引库

注意:es里不能修改已有字段,可以给索引库添加字段

因为创建好索引库后,es会构建倒排索引,这个过程是比较消耗性能的。

一旦索引库的某个字段被修改,可能会导致原本的倒排索引失效,影响太大,

所以es不能修改索引库中已有的字段。

语法

PUT /索引库名/_mapping
{"properties":{"新字段名":{"type": "类型","index": true,...},"新字段名":{"type": "类型","index": true,...},...}
}#4.修改索引库
# 不允许修改已有字段,只能新增字段
PUT /suoyinku/_mapping
{"properties":{"email":{"type":"keyword"}}
}

2.2.4 删除索引库

语法

DELETE /索引库名#5.删除索引库
DELETE /suoyinku

2.3 练习

要求1:创建一个索引库itcast,用于存储商品信息。要有以下字段:

  • 商品id id

  • 商品名称 title

  • 商品价格 price

  • 所属品牌 brand

  • 商品库存量 quantity

  • 商品图片url地址 images

要求2:查看索引库itcast的信息

要求3:给索引库itcast增加一个字段“商品分类 category”

要求4:删除索引库itcast

3. 小结

ES的一些概念:
    Index:索引库,相当于MySQL里的表
    Document:文档,一个文档是json格式,相当于MySQL里的一行数据
    Field:字段,相当于MySQL里的字段
    Mapping:映射,相当于MySQL里的表结构 每个字段的名称、类型、约束等等
    DSL:操作ES的语句,相当于MySQL里的SQL语句


操作索引库的DSL命令:
    新增:
        PUT /索引库名
        {
            "mappings":{
                "properties":{
                    "字段名":{
                        "type": "类型",
                        "analyzer": "分词器",
                        "index": 是否参与搜索
                    },
                    ...,
                    "字段名":{
                        "type": "类型",
                        "analyzer": "分词器",
                        "index": 是否参与搜索
                    }
                }
            }
        }
    查看:
        GET /_cat/indices   查询所有索引库
        GET /索引库名        查看索引库详细信息
    修改:只能新增字段,不能修改已有字段
        PUT /索引库名/_mapping
        {
            "properties":{
                "字段名":{
                "type": "类型",
                "analyzer": "分词器",
                "index": 是否参与搜索
                },
                ...,
                "字段名":{
                "type": "类型",
                "analyzer": "分词器",
                "index": 是否参与搜索
                }
            }
        }
    删除:
        DELETE /索引库名

四、操作文档

掌握文档的CURD参考:Document APIs | Elasticsearch Guide [7.4] | Elastic

1. 新增文档

语法:

PUT /索引库名/_doc/[id]
{"key": value,..."key": value
}-------------------------------------------
#id:文档的主键值#示例
------------------------------------------
#0.查询所有索引库
GET /_cat/indices
GET /suoyinku#1.保存一条文档数据:
#   如果唯一标识对应数据不存在,是新增
#   如果唯一标识对应的数据存在,是覆盖式修改
PUT /suoyinku/_doc/1
{"id":1,"name":"凉介","age":"26","email":"huiyishi@163.com","sex":"男","avatar":"http//:www.baidu.com/abc.jpg","score":59
}

2. 查看文档

语法

#语法:
GET /索引库名/_doc/id#示例:
#2.查询文档
GET /suoyinku/_doc/1

3. 删除文档

语法

#语法:
DELETE /索引库名/_doc/id值#示例
#3.删除文档
DELETE /suoyinku/_doc/1

4. 修改文档

语法

方式一:全量修改

全量修改操作,会删除旧文档,添加新文档

如果唯一标识对应数据不存在,是新增

PUT /索引库名/_doc/文档id
{"字段1": 值1,"字段2": 值2,...
}#示例1
#在刚才已删除的基础上  修改
#如果唯一标识对应数据不存在,是新增
#则实际操作的为:新增
PUT /shuoyinku/_doc/1
{"id":1,"name":"凉介","age":"26","email":"huiyishi@163.com","sex":"男","avatar":"http//:www.baidu.com/abc.jpg","score":59
}
结果:
{"_index" : "shuoyinku","_type" : "_doc","_id" : "1","_version" : 1,"result" : "created","_shards" : {"total" : 2,"successful" : 1,"failed" : 0},"_seq_no" : 0,"_primary_term" : 1
}

2.如果唯一标识对应的数据已存在,是覆盖式修改

-------------------------------------
#示列2
#在刚才已修改的基础上  唯一标识不存在则是:新增
#如果唯一标识对应的数据已存在,是覆盖式修改
PUT /shuoyinku/_doc/1
{"id":1,"name":"小凉介","age":"26","email":"huiyishi@163.com","sex":"男","avatar":"http//:www.baidu.com/abc.jpg","score":89
}
#------------------------------------
#返结果响应:updated
{"_index" : "shuoyinku","_type" : "_doc","_id" : "1","_version" : 2,"result" : "updated","_shards" : {"total" : 2,"successful" : 1,"failed" : 0},"_seq_no" : 1,"_primary_term" : 1
}

 对比 :

方式二:增量修改

增量修改操作,只修改指定字段值

POST /索引库名/_update/文档id
{"doc":{"字段1": 值1,"字段2": 值2,...}
}
#示例
#方式二:
#增量修改文档:
#在原始文档基础上修改,不常用
POST /shuoyinku/_update/1
{"doc":{"age":40}
}

5. 查询所有文档

语法

#语法:
POST /索引库名/_search   #示例:
POST /shuoyinku/_search

6. 动态映射【拓展了解】

思考

如果新增文档的结构,与mapping结构不一致,会出现什么结果

例如

#插入的文档结构,与mapping结构不符。
#itcast索引库中原本没有color、weight、stock、isSoldOut四个字段
PUT /itcast/_doc/2
{"title": "罗技鼠标","price": 89,"images": "http://www.jd.com/xxxx.jpg","stock": 50,"weight": 0.22,"color": "black","isSoldOut": false
}

查询索引的映射:GET /itcast/_mapping

看到结果

{"itcast" : {"mappings" : {"properties" : {"color" : { #增加了color字段,是字符串。ES无法判断类型,因此存储了两种映射类型。color是text类型,color.keyword是keyword类型"type" : "text","fields" : {"keyword" : {"type" : "keyword","ignore_above" : 256}}},"images" : {"type" : "keyword","index" : false},"isSoldOut" : { #增加了isSoldOut字段,类型boolean"type" : "boolean"},"price" : {"type" : "double"},"stock" : { #增加了stock字段,类型long"type" : "long"},"title" : {"type" : "text","analyzer" : "ik_smart"},"weight" : { #增加了weight字段,类型float"type" : "float"}}}}
}

说明

插入文档时,es会检查文档中的字段是否有对应的mapping,如果没有,则按照默认的mapping规则来创建索引。

如果默认的mapping不符合你的要求,一定要自己设置字段的mapping

6. 小结

1. 保存文档
   如果唯一标识对应的文档不存在:是新增
   如果唯一标识对应的文档已存在:是覆盖式修改,直接把原始文档数据全部覆盖掉
   PUT /索引库名/_doc/唯一标识
   {
        "字段名": 值,
        "字段名": 值,
        ...
        "字段名": 值
   }
2. 查看文档
   GET /索引库名/_doc/唯一标识
3. 增量修改文档,不常用。在原始文档基础上做修改
   POST /索引库名/_update/唯一标识
   {
       "doc":{
        "字段名": 值,
        "字段名": 值,
        ...
        "字段名": 值           
       }
   }
4. 删除文档:
   DELETE /索引库名/_doc/唯一标识
5. 查询所有文档
   POST /索引库名/_search

五、RestAPI

1. 准备工作

1.1 创建project导入依赖

导入es的客户端依赖坐标

注意:es客户端依赖的版本号,必须要和es的版本号一致

<dependencies><!--es客户端--><dependency><groupId>org.elasticsearch.client</groupId><artifactId>elasticsearch-rest-high-level-client</artifactId><version>7.4.0</version></dependency><!-- https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-api --><dependency><groupId>org.junit.jupiter</groupId><artifactId>junit-jupiter-api</artifactId><version>5.8.2</version></dependency><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.70</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.16.10</version></dependency>
</dependencies>

1.2 创建实体类

商品Product,对应es里的product索引

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Product {private Long id;/**标题*/private String title;/**分类*/private String category;/**品牌*/private String brand;/**价格*/private Double price;/**图片地址*/private String images;
}

​​​​​1.3 RestAPI的使用说明

要想操作es,需要按照如下步骤:

  1. 创建RestHighLevelClient对象

  2. 使用RestHighLevelClient操作es

  3. 关闭RestHighLevelClient

//1. 创建RestHighLevelClient客户端对象。
//   如果连接ES集群,就写多个地址;
//   如果是单ES实例,就只写一个地址
RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(new HttpHost("localhost", 9201),new HttpHost("localhost", 9202),new HttpHost("localhost", 9203)
));//2. 使用client操作es//3. 关闭client
client.close();

2. 操作索引【了解】

2.1 API说明

RestHighLevelClient对象提供了操作索引库的API方法,常用的有:

  • 创建:

     restClient.indices()

     .create(CreateIndexRequest request, RequestOptions options)

  • 删除:

     restClient.indices()

    .delete(DeleteIndexRequest request, RequestOptions options)

  • 是否存在:

        restClient.indices()

        .exists(GetIndexRequest request, RequestOptions options)

以上方法的参数:

  • CreateIndexRequest创建索引库的请求对象

  • DeleteIndexRequest删除索引库的请求对象

  • GetIndexRequest查询索引库的请求对象

  • RequestOptions创建索引库的请求选项使用固定值RequestOptions.DEFAULT即可

注意事项:

使用RestAPI创建索引库非常繁琐,建议在Kibana里使用DSL语句执行操作,而不是用Java代码创建索引库

2.2 使用示例

索引库分析:

要把一条商品信息存储到es,我们要先分析一下对应的索引库及映射该如何编写:

  • id: 商品id,主键,可以使用long类型

  • title:商品名称,使用text类型,要分词并构建倒排索引进行搜索

  • category:商品分类,分类是整体,不进行分词,使用keyword

  • brand:品牌,和分类类似,不进行分词,使用keyword

  • price:价格,double类型

  • images:图片地址,用来展示的字段,不需要构建索引,不参与搜索;index设置为false,使用keyword类型

 编辑DSL命令如下:

PUT /product
{"mappings":{"properties":{"id":{"type": "long"},"title":{"type": "text","analyzer": "ik_max_word"},"category":{"type": "keyword"},"brand":{"type": "keyword"},"price":{"type": "double"},"images":{"type": "keyword","index": false}}}
}

操作示例

准备工作:

/** 使用RestAPI操作ES的步骤:*  创建客户端对象,连接ES*  使用客户端对象,操作ES*  关闭客户端对象,断开连接* API:*  客户端对象:RestHighLevelClient** ctrl+alt+f:把选中的变量提取成为Field成员变量* ctrl+alt+m:把选中的代码提取成为Method成员方法* ctrl+alt+v:所选中的代码提取给一个Variable局部变量*/
public class Demo01Es {private RestHighLevelClient client;@Testpublic void test(){//使用客户端对象,操作ES}@Testpublic void test2(){//使用客户端对象,操作ES}@BeforeEachpublic void init(){//创建客户端对象,连接ESnew RestHighLevelClient(RestClient.builder(new HttpHost("localhost",9200)));}@AfterEachpublic void destroy() throws IOException {//关闭客户端对象,断开连接client.close();}
}
//@BeforeAll   注解表示在 所有 测试方法执行之前执行一次,并且必须是静态方法。//通常用于初始化测试环境,例如启动一个数据库连接池或者读取测试数据文件。
//@BeforeEach  注解表示在 每个 测试方法执行之前执行一次。方法不能是静态的 。// 通常用于初始化测试数据或者创建被测试对象的实例。

使用RestHighLevelClient操作的示例代码如下:

public class Demo01Index {private RestHighLevelClient client;@Testpublic void testCreateIndex() throws IOException {String json = "{\n" +"  \"mappings\":{\n" +"    \"properties\":{\n" +"      \"id\":{\n" +"        \"type\":\"long\"\n" +"      },\n" +"      \"title\":{\n" +"        \"type\":\"text\",\n" +"        \"analyzer\":\"ik_max_word\"\n" +"      },\n" +"      \"category\":{\n" +"        \"type\":\"keyword\"\n" +"      },\n" +"      \"brand\":{\n" +"        \"type\":\"keyword\"\n" +"      },\n" +"      \"price\":{\n" +"        \"type\":\"double\"\n" +"      },\n" +"      \"images\":{\n" +"        \"type\":\"keyword\",\n" +"        \"index\":false\n" +"      }\n" +"    }\n" +"  }\n" +"}";//创建索引库CreateIndexRequest request = new CreateIndexRequest("product").source(json, XContentType.JSON);client.indices().create(request, RequestOptions.DEFAULT);}@Testpublic void testDeleteIndex() throws IOException {//删除索引库DeleteIndexRequest request = new DeleteIndexRequest("product");client.indices().delete(request, RequestOptions.DEFAULT);}@Testpublic void testExistsIndex() throws IOException {//索引库是否存在GetIndexRequest request = new GetIndexRequest("product");boolean exists = client.indices().exists(request, RequestOptions.DEFAULT);System.out.println(exists);}@BeforeEachpublic void init() {// 创建客户端对象,连接ESclient = new RestHighLevelClient(RestClient.builder(new HttpHost("localhost", 9200)));}@AfterEachpublic void destroy() throws IOException {// 关闭客户端对象,断开连接client.close();}
}

@BeforeEach和@BeforeAll

//@BeforeAll   注解表示在 所有 测试方法执行之前执行一次,并且必须是静态方法。通常用于初始化测试环境,例如启动一个数据库连接池或者读取测试数据文件。

//@BeforeEach  注解表示在 每个 测试方法执行之前执行一次。方法不能是静态的 。通常用于初始化测试数据或者创建被测试对象的实例。

3. 操作文档【重点】

3.1 API说明

使用Java操作文档,和在kibana里编写DSl非常类似

只是由Java代码来执行相同的操作

RestHighLevelClient提供了操作文档的API如下:

  • 新增与修改:client.index(IndexRequest request, RequestOptions options)

  • 查看client.get(GetRequest request, RequestOptions options)

  • 删除:client.delete(DeleteRequest request, RequestOptions options)

  • 批量操作文件:client.bulk(BulkRequest request,RequestOptions options)

以上方法的参数:

  • IndexRequest新增与修改文档的请求对象

  • GetRequest查询文档的请求对象

  • DeleteRequest删除文档的请求对象

  • RequestOptions请求选项参数,使用固定值RequestOptions.DEFAULT即可

3.2 使用示例

新增或修改

查询:

删除:

完整代码

public class Demo03Document {private RestHighLevelClient client;//新增或修改@Testpublic void testSave() throws IOException {Product product = new Product(2L, "桌子", "家具", "欧斯曼",4500D, "http://images.huawei.com/pro40.jpg");IndexRequest request = new IndexRequest("product").id(product.getId().toString()).source(JSON.toJSONString(product), XContentType.JSON);client.index(request, RequestOptions.DEFAULT);}//查询@Testpublic void testGet() throws IOException {GetRequest request = new GetRequest("product").id("2");//向ES发RESTful请求,得到响应结果。响应结果就是查询结果GetResponse response = client.get(request, RequestOptions.DEFAULT);//从结果里获取_source,得到json格式的字符串String docJson = response.getSourceAsString();//把JSON格式的字符串,还原成JavaBean对象Product product = JSON.parseObject(docJson, Product.class);System.out.println("product = " + product);}@Testpublic void testDelete() throws IOException {//删除DeleteRequest request = new DeleteRequest("product").id("2");client.delete(request, RequestOptions.DEFAULT);}@BeforeEachpublic void init() {//创建客户端对象,连接ESclient = new RestHighLevelClient(RestClient.builder(new HttpHost("localhost", 9200)));}@AfterEachpublic void destroy() throws IOException {//关闭客户端对象 ,断开连接client.close();}
}

4. 批量操作文档

4.1 说明

批量操作的核心在于将多个普通请求封装在一个批量请求中,一次性发送到服务器,下面仅仅演示批量新增(其他自己尝试)

操作的步骤:

  1. 准备BulkRequest对象

  2. 把每个文档数据,封装到一个IndexRequest对象里。

  3. 把IndexRequest添加到BulkRequest对象中

  4. 使用client.bulk(bulkRequest对象, RequestOptions.DEFAULT)

4.2 示例

public class Demo03Document {private RestHighLevelClient client;//批量操作文件@Testpublic void testBulkDocument() throws IOException {ArrayList<Product> list = new ArrayList<>();list.add(new Product(11L, "小米手机", "手机数码", "小米", 3299.00, "http://image.huawei.com/13123.jpg"));list.add(new Product(12L, "锤子手机", "手机数码", "锤子", 3699.00, "http://image.huawei.com/13123.jpg"));list.add(new Product(13L, "联想手机", "手机数码", "联想", 4499.00, "http://image.huawei.com/13123.jpg"));list.add(new Product(14L, "红米手机", "手机数码", "小米", 4299.00, "http://image.huawei.com/13123.jpg"));list.add(new Product(15L, "iPhone X", "手机数码", "苹果", 8299.00, "http://image.huawei.com/13123.jpg"));list.add(new Product(16L, "MacBook pro", "电脑", "苹果", 14999.00, "http://image.huawei.com/13123.jpg"));list.add(new Product(17L, "AirPods", "手机数码", "苹果", 4299.00, "http://image.huawei.com/13123.jpg"));list.add(new Product(18L, "外星人", "电脑", "DELL", 21299.00, "http://image.huawei.com/13123.jpg"));list.add(new Product(19L, "联想小新", "电脑", "联想", 6299.00, "http://image.huawei.com/13123.jpg"));//1.创建一个bulkrequest对象BulkRequest request = new BulkRequest();//2.添加数据for (Product product : list) {//2.1 把一个Product对象,封装到一个IndexRequest对象里IndexRequest indexRequest = new IndexRequest("product").id(product.getId().toString()).source(JSON.toJSONString(product),XContentType.JSON);//把IndesRequest对象添加到BulkRequest对象里面request.add(indexRequest);}client.bulk(request,RequestOptions.DEFAULT);}@BeforeEachpublic void init() {//创建客户端对象,连接ESclient = new RestHighLevelClient(RestClient.builder(new HttpHost("localhost", 9200)));}@AfterEachpublic void destroy() throws IOException {//关闭客户端对象 ,断开连接client.close();}
}

5. 小结

1. 使用RestHighLevelClient操作ES的统一步骤:
    创建RestHighLevelClient对象
        RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(
            new HttpHost("ip", 9200)
        ));
    使用RestHighLevelClient操作ES
    关闭RestHighLevelClient对象
        client.close();

2. 操作索引库的API
    创建:client.indices().create(CreateIndexRequest request, RequestOptions options);
        注意:使用CreateIndexRequest是全类名短的那个
    删除:client.indices().delete(DeleteIndexRequest request, RequestOptions options);
    是否存在:client.indices().exists(GetIndexRequest reuqest, RequestOptions options);
        注意:使用GetIndexRequest是全类名短的那个

3. 操作文档的API
    保存(新增与修改):client.index(IndexRequest request, RequestOptions options);
    查询:client.get(GetRequest request, RequestOptions options);
    删除:client.delete(DeleteRequest request, RequestOptions options);
    批量操作文件:client.bulk(BulkRequest request, RequestOptions options);

六、练习

需求

执行SQL脚本《资料/tb_hotel.sql》,其中有tb_hotel表,存储了酒店的数据

利用BulkRequest批量将数据库数据导入到索引库中。

步骤

  1. 根据数据库表结构,在es里创建对应的索引库

  2. 使用Java程序读取MySQL数据,再使用RestHighLevelClient存储到es的索引库里

实现

1. 创建索引库

# 创建酒店索引
PUT /hotel
{"mappings": {"properties": {"id":{"type": "long"},"name":{"type": "text","analyzer": "ik_max_word","copy_to": "all"},"address":{"type": "text","analyzer": "ik_smart","copy_to": "all"},"price":{"type": "integer"},"score":{"type": "integer"},"brand":{"type": "keyword","copy_to": "all"},"city":{"type": "keyword","copy_to": "all"},"starName":{"type": "keyword"},"business":{"type": "keyword","copy_to": "all"},"location":{"type": "geo_point"},"pic":{"type": "keyword","index": false},"all":{"type": "text","analyzer": "ik_max_word"}}}
}

2. 准备环境

创建一个新的project,执行以下步骤:

导入依赖

<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.3.9.RELEASE</version>
</parent><!--全局锁定ES客户端的版本号-->
<properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target><elasticsearch.version>7.4.0</elasticsearch.version>
</properties><dependencies><!--es客户端--><dependency><groupId>org.elasticsearch.client</groupId><artifactId>elasticsearch-rest-high-level-client</artifactId></dependency><!-- web起步依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- mp和mysql --><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.4.0</version></dependency><dependency><groupId>com.mysql</groupId><artifactId>mysql-connector-j</artifactId><version>8.0.33</version></dependency><!-- 单元测试 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId></dependency><!-- json转换 --><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.70</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency>
</dependencies>

配置文件

spring:datasource:driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql:///es?useSSL=falseusername: rootpassword: root

引导类

@SpringBootApplication
@MapperScan("com.esrestapi.mapper")
public class HotelApplication {public static void main(String[] args) {SpringApplication.run(HotelApplication.class,args);}
}

实体类Hotel

@Data
@TableName("tb_hotle")
public class Hotel {@TableId(type = IdType.AUTO)private Long id;private String name;private String address;private Integer price;private Integer score;private String brand;private String city;private String starName;private String business;private String longitude;private String latitude;private String pic;
}

实体类HotelDoc

@Data
@NoArgsConstructor
public class HotelDoc {private Long id;private String name;private String address;private Integer price;private Integer score;private String brand;private String city;private String starName;private String business;private String location;private String pic;public HotelDoc(Hotel hotel){this.id = hotel.getId();this.name = hotel.getName();this.address = hotel.getAddress();this.price = hotel.getPrice();this.score = hotel.getScore();this.brand = hotel.getBrand();this.city = hotel.getCity();this.starName = hotel.getStarName();this.business = hotel.getBusiness();this.location = hotel.getLatitude() + ", " + hotel.getLongitude();this.pic = hotel.getPic();}
}

HotelMapper

public interface HotelMapper extends BaseMapper<Hotel> {
}

3. 批量插入数据

@SpringBootTest
public class HotelTest {@Autowiredprivate HotelMapper hotelMapper;@Autowiredprivate RestHighLevelClient esClient;@Testpublic void test() throws IOException {//1. 读取数据库里所有的酒店数据List<Hotel> list = hotelMapper.selectList(null);//2. 循环酒店列表,把每个酒店数据添加到BulkRequest对象里BulkRequest bulkRequest = new BulkRequest();for (Hotel hotel : list) {//把每个Hotel对象转换成对应ES的HotelDoc对象HotelDoc hotelDoc = new HotelDoc(hotel);//创建IndexRequest对象IndexRequest request = new IndexRequest("hotel").id(hotelDoc.getId().toString()).source(JSON.toJSONString(hotelDoc), XContentType.JSON);bulkRequest.add(request);}//3. 执行批量插入esClient.bulk(bulkRequest, RequestOptions.DEFAULT);//4. 关闭连接//client.close();}
}

ElasticSearch入门简介、安装ES(安装Kibana和IK分词器)使用 Postman连接ES进行测、ESRestAPI(操作索引CRUD操作文档CRUD)、练习相关推荐

  1. Docker安装ElasticSerach、ElasticSerachhead、IK分词器及Kibanna步骤(亲测能用)

    前言:网上有很多文章描述关于Docker安装ElasticSerach.ElasticSerachhead.IK分词器及Kibanna步骤.流程及注意事项.我试了很多,综合整理出此文,此文中有些地方是 ...

  2. ES入门学习:ElasticSearch、Kibana、ik分词器的安装、简单使用及SpringBoot集成

    前言 es是采用Java语言开发,因此,想要安装运行es需要提前准备好jdk环境,关于linux配置jdk在前文linux配置jdk 本文主要介绍es的安装.kibana的安装和简单使用及ik分词器的 ...

  3. 服务器安装配置elasticsearch,kibana,IK分词器和拼音分词器,集群搭建教程

    docker安装配置elasticsearch,kibana和IK分词器 elasticsearch文章系列 前置安装docker 创建docker网络 安装Elasticsearch 运行elast ...

  4. [Linux]Linux下安装和配置solr/tomcat/IK分词器 详细实例二.

    为了更好的排版, 所以将IK分词器的安装重启了一篇博文,  大家可以接上solr的安装一同查看. [Linux]Linux下安装和配置solr/tomcat/IK分词器 详细实例一: http://w ...

  5. Linux下安装和配置solr/tomcat/IK分词器 详细实例二.

    为了更好的排版, 所以将IK分词器的安装重启了一篇博文,  大家可以接上solr的安装一同查看. [Linux]Linux下安装和配置solr/tomcat/IK分词器 详细实例一: http://w ...

  6. es安全组端口_从零开始在远程服务器(Linux)上搭建es,eshead和ik分词器

    一.资源准备 远程服务器一个(本教程为CentOS 64位) 注:ik分词器版本需与es版本统一 jdk1.8.0 elasticsearch-head-master.zip 二.开放端口 注:本例采 ...

  7. ElasticSearch学习笔记之十一 Anayle API和IK分词器

    ElasticSearch学习笔记之十一 Anayle API和IK分词器 Anayle API IK分词器 IK分词器版本支持 安装 下载或者编译 选择一 选择二 重启ElasticSearch I ...

  8. ES集群添加IK分词器

    ES集群添加IK分词器 ES : 7.5.0 官方文档其实已经够优秀了,毕竟是中文的,这里只给出一些建议. IKAnalyzer.cfg.xml 建议放到插件的目录下,要不然有可能会有一些问题 {pl ...

  9. Docker 安装 ES 7.7.0 及 Head、Kibana、IK分词器、Logstash、Filebeat 插件

    目录 环境信息 ES安装 ElasticSearch-Head安装 IK分词器安装 环境信息 Docker version 1.13.1, build 4ef4b30/1.13.1 CentOS Li ...

最新文章

  1. 对抗性攻击轻松愚弄人工智能
  2. RxJava flatMap操作符用法详解
  3. 《魂斗罗:归来》手游子弹中没中,没你想得那么简单!
  4. Java项目课程04:需求分析
  5. web项目里看不到html,在webpack中导入html文件时找不到模块错误
  6. em,rem,px的实际应用
  7. 什么是 POD 数据类型
  8. 怎样用UE4把一个Actor直接打包成Pak
  9. Jmeter接口测试及接口性能测试
  10. 18个Windows应该有却没有具有的苦守(2)
  11. 【Ubuntu】检测内存并压力测试
  12. 1200PLC学习资料整理
  13. 品牌连锁店5G/4G无线组网方案
  14. 怎么批量下载Onedrive分享文件_怎么用PS弄字幕文件 PS批量生成字幕制作教程
  15. 【C语言】猴子吃桃问题。猴子第1天摘下若干个桃子,当即吃了一半,还不过瘾,又多吃了一个。第2天早上又将剩下的桃子吃掉一半,又多吃了一个。以后每天早上都吃了前一天剩下的一半零一个。到第10天早上想……
  16. 指针:C语言二级指针与二维数组
  17. 手机运行慢可以刷机吗_智能手机反应慢怎么处理?【详解】
  18. 效率系列(二) Win10常用快捷键
  19. 车联网解决方案一DSRC与C-V2X对比
  20. 知识图谱从入门到应用——知识图谱推理:基于表示学习的知识图谱推理-[嵌入学习]

热门文章

  1. 数据库优化一般思路(个人经验之谈)
  2. 李彦宏:中国互联网大局未定 好戏还在后面
  3. a标签中href=的几种跳转方法
  4. 基于redis实现的投票系统
  5. UDP 反向代理设计方案
  6. 遇险无线电信标的全球与中国市场2022-2028年:技术、参与者、趋势、市场规模及占有率研究报告
  7. Nubia Z9 mini使用体验
  8. USBASP USB Programmer
  9. 清览云题库--数据可视化
  10. 第六章图-算法6.8普里姆算法