ES快速入门
目录
利用JavaRestClient实现创建、删除索引库,判断索引库是否存在
操作文档——利用JavaResyClient实现文档的CRUD
初识ES
什么是elasticsearch
elasticsearch是一款非常强大的开源搜索引擎,可以帮助我们从海量数据中快速找到需要的内容
elasticsearch结合kibana、Logstash、Beats,也就是elastic stack (ELK)。被广泛应用在日志数据分析、实时监控
elasticsearch:elk的核心,负责存储,搜索,分析数据。
logstash、beats:主要负责数据抓取
kibana:数据可视化,展示数据形成报表
正排和倒排索引
正向索引
正排索引:由文档指向关键字
文档->单词1,单词2,单词3
单词1:单词1出现次数,单词1所处位置
正排索引:适用于在搜索栏中搜索id
当用户在搜索栏中搜索关键字地时候,如果只存在正排索引,那么就需要扫描索引库中地所有文档,判断是否包含关键词,再根据打分模型进行打分,排出名次再呈现给用户。
但是这种索引结构不适用大数据量地情况
倒排索引
结构如下:
倒排索引:由关键字指向文档
单词1 ->文档1,文档2,文档3
单词2 ->文档1,文档2
倒排索引:将搜索框中地词进行搜索查询哪些文档包含这个词条,然后再查询这些文档
对文档内容分词,对词条创建索引,并记录词条所在文档的信息。查询时先根据词条查询到文档id,而后获取到文档
倒排索引中有非常重要的两个概念:
- 文档(Document):每一条数据其实就是一个文档,比如一个网页,一个商品信息
- 词条(Term):根据文档数据利用某种算法分词,得到的具备含义的词语就是词条
创建倒排索引是对正向索引的一种特殊处理:
- 将每个文档的数据利用分词算法进行分词,得到词条
- 创建表,每行的数据包含词条以及词条对应的文档id
- 因为词条有唯一性,所以可以给词条创建索引
倒排索引的搜索流程:
以搜索华为手机为例子
- 用户搜索华为手机
- 对搜索内容'华为手机'进行分词,得到'华为'、'手机'两个词条
- 去词条列表中查询文档id,得到每个词条所在的文档id:华为2,3 手机1,2
- 根据文档id查询文档,得到id为1,2,3的文档存入结果集
es和mysql的概念对比
1:elasticsearch是面向文档存储的,可以是数据库中的一条商品数据,一个订单信息文档数据会被序列化为json格式后存储在elasticsearch中。
2:elasticsearch里的索引是相同类型的文档集合,按照文档的类型进行划分,比如给商品类型一类文档添加商品索引、用户类型的一类文档添加用户索引,有点像数据库种一个表的感觉,如图:
概念对比
- mysql中的表对应的就是es中的索引,只不过索引是文档的集合
- mysql中的行数据对应es中的文档,只不过文档都是JSON格式
- mysql中的字段对应的是es中的FieId(字段)
- mysql中的schema字段类型约束对应es中的Mapping(映射)
- mysql中用的是SQL语句,es使用是es提供的JSON风格请求语句DSL
架构
Mysql:擅长事务类型的操作,里面有acid的原则-可以确保数据的安全和一致性
ES:擅长海量数据的搜索、分析、计算
单点部署
1.部署单点es
1.1.创建网络
因为我们还需要部署kibana容器,因此需要让es和kibana容器互联。这里先创建一个网络:
docker network create es-net
1.2这里我们采用elasticsearch的7.12.1版本的镜像,然后加载到docker镜像中
docker load -i es.tar
1.3运行docker命令,部署单点es:
```sh
docker run -d \
--name es \
-e "ES_JAVA_OPTS=-Xms512m -Xmx512m" \
-e "discovery.type=single-node" \
-v es-data:/usr/share/elasticsearch/data \
-v es-plugins:/usr/share/elasticsearch/plugins \
--privileged \
--network es-net \
-p 9200:9200 \
-p 9300:9300 \
elasticsearch:7.12.1
```
命令解释:
- `-e "cluster.name=es-docker-cluster"`:设置集群名称
- `-e "http.host=0.0.0.0"`:监听的地址,可以外网访问
- `-e "ES_JAVA_OPTS=-Xms512m -Xmx512m"`:内存大小
- `-e "discovery.type=single-node"`:非集群模式
- `-v es-data:/usr/share/elasticsearch/data`:挂载逻辑卷,绑定es的数据目录
- `-v es-logs:/usr/share/elasticsearch/logs`:挂载逻辑卷,绑定es的日志目录
- `-v es-plugins:/usr/share/elasticsearch/plugins`:挂载逻辑卷,绑定es的插件目录
- `--privileged`:授予逻辑卷访问权
- `--network es-net` :加入一个名为es-net的网络中
- `-p 9200:9200`:端口映射配置
在浏览器中输入:http://192.168.150.101:9200 即可看到elasticsearch的响应结果
2.部署kibana
2.1部署
运行docker命令,部署kibana
docker run -d \
--name kibana \
-e ELASTICSEARCH_HOSTS=http://es:9200 \
--network=es-net \
-p 5601:5601 \
kibana:7.12.1
-network es-net` :加入一个名为es-net的网络中,与elasticsearch在同一个网络中
-e ELASTICSEARCH_HOSTS=http://es:9200"`:设置elasticsearch的地址,因为kibana已经与elasticsearch在一个网络,因此可以用容器名直接访问elasticsearch
-p 5601:5601`:端口映射配置
2.2启动、kibana启动一般比较慢,需要多等待一会,可以通过命令:
docker logs -f kibana
查看运行日志,当查看到下面的日志,说明成功:
此时,在浏览器输入地址访问:http://192.168.150.101:5601,即可看到结果
分词器
es在创建倒排索引时需要对文档分词;在搜索时,需要对用户输入内容分词。但默认的分词规则对中文处理并不友好
这里我们推荐安装IK分词器
IK分词器有两种模式:
ik_smart:最粗粒度切分
ik_max_word: 最细粒度切分
#测试分词器
POST /_analyze
{
"text": "珠海科技学院java太棒了",
"analyzer": "ik_smart"
}
#测试分词器
POST /_analyze
{
"text": "珠海科技学院java太棒了",
"analyzer": "ik_max_word"
}
结果如上图所示:可以得出ik_max_word进行的切分会比ik_smart切分出的关键词更多,粒度更细
IK分词器的拓展和停用字典
IK分词器的拓展:
要拓展ik分词器的词库,只需要修改一个ik分词器目录中的config目录中的IKAnalyzer.cfg.xml文件,如下图所示:
如果要禁用某些敏感词汇,只需要在上面这个文件中添加字段,如下图所示:
上面配置的拓展词和停止词文件是在当前IKAnalyzer.cfg.xml文件所在目录下
索引库操作
mapping映射
mapping是对索引库中文档的约束,常见的mapping属性包括
- type:字段数据类型,常见的简单类型有:
-
- 字符串: text (可分词的文本)、keyword (精确值,例如:品牌、国家、ip地址)
- 数值: long、integer、short、byte、double、float
- 布尔: boolean
- 日期: date
- 对象:object
- index:是否创建索引,默认为true
- analyzer:使用哪种分词器
- properties:该字段的子字段
创建索引库
ES中通过Restful请求操作索引库、文档。请求内容用DSL语句来表示。创建索引库和mapping的DSL语法如下:
索引库操作
文档操作
如果文档id不指定会随机生成
RestClient操作索引库
什么是RestClient
利用JavaRestClient实现创建、删除索引库,判断索引库是否存在
根据课前资料提供的酒店数据创建索引库,索引库名为hotel,mapping属性根据数据库结构定义。基本步骤如下:
1.导入课前资料Demo
2.分析数据结构,定义mapping属性
3.初始化JavaRestClient
4.利用JavaRestClient创建索引库
5.利用JavaRestClient删除索引库
6.利用JavaRestClient判断索引库是否存在
分析数据结构,定义mapping属性
分析出的索引定义语句如下
#酒店的mapping
PUT /hotal1
{
"mappings": {
"properties": {
"id": {
"type": "keyword"
},
"name": {
"type": "text",
"analyzer": "ik_max_word",
"copy_to": "{all}"
},
"address": {
"type": "keyword",
"index": false
},
"price": {
"type": "integer"
},
"score": {
"type": "integer"
},
"brand": {
"type": "keyword",
"copy_to": "{all}"
},
"city": {
"type": "keyword"
},
"starName": {
"type": "keyword"
},
"business": {
"type": "keyword",
"copy_to": "{all}"
},
"location": {
"type": "geo_point"
},
"uri": {
"type": "keyword",
"index": false
},
"all": {
"type": "text",
"analyzer": "ik_max_word"
}
}
}
}
提示:
ES中支持两种地理坐标数据类型:
geo_point:由纬度(latitude)和经度(longitude)确定的一个点。例如:"32.8752345,120.2981576”
geo_shape:有多个geo_point组成的复杂几何图形。例如一条直线, "LINESTRING(-77.03653 38897676,77.009051 38.889939)
tips:字段拷贝可以使用copy_to属性将当前字段拷贝到指定字段。示例
初始化JavaRestClient
创建索引库
MAPPING_TEMPLATE代码如下:
public class HotelConstants {
public static final String MAPPING_TEMPLATE =
"{\n" +
" \"mappings\": {\n" +
" \"properties\": {\n" +
" \"id\": {\n" +
" \"type\": \"keyword\"\n" +
" },\n" +
" \"name\": {\n" +
" \"type\": \"text\",\n" +
" \"analyzer\": \"ik_max_word\",\n" +
" \"copy_to\": \"{all}\"\n" +
" },\n" +
" \"address\": {\n" +
" \"type\": \"keyword\",\n" +
" \"index\": false\n" +
" },\n" +
" \"price\": {\n" +
" \"type\": \"integer\"\n" +
" },\n" +
" \"score\": {\n" +
" \"type\": \"integer\"\n" +
" },\n" +
" \"brand\": {\n" +
" \"type\": \"keyword\",\n" +
" \"copy_to\": \"{all}\"\n" +
" },\n" +
" \"city\": {\n" +
" \"type\": \"keyword\"\n" +
" },\n" +
" \"starName\": {\n" +
" \"type\": \"keyword\"\n" +
" },\n" +
" \"business\": {\n" +
" \"type\": \"keyword\",\n" +
" \"copy_to\": \"{all}\"\n" +
" },\n" +
" \"location\": {\n" +
" \"type\": \"geo_point\"\n" +
" },\n" +
" \"uri\": {\n" +
" \"type\": \"keyword\",\n" +
" \"index\": false\n" +
" },\n" +
" \"all\": {\n" +
" \"type\": \"text\",\n" +
" \"analyzer\": \"ik_max_word\"\n" +
" }\n" +
" \n" +
" \n" +
"}\n" +
" } ";
}
删除索引库、判断索引库是否存在
操作文档——利用JavaResyClient实现文档的CRUD
去数据库查询酒店数据,导入到hotel索引库,实现酒店数据的CRUD基本步骤如下
1.初始化JavaRestClient
2.利用JavaRestClient新增酒店数据
3.利用avaRestClient根据id查询酒店数据
4.利用lavaRestClient删除酒店数据5.利用JavaRestClient修改酒店数据
新建文档的语句如下:
文档操作的基本步骤
- 初始化RestHighLevelClient
- 创建XxxRequest。XXX是Index、Get、Update、Delete
- 准备参数 (Index和Update时需要)
- 发送请求。调用RestHighLevelClient#.xxx()方法,xxx是index、get、update、delete
- 解析结果(Get时需要)
操作文档——批量导入功能
需求:批量查询酒店数据,然后批量导入索引库中思路
1.利用mybatis-plus查询酒店数据
2将查询到的酒店数据 (Hotel) 转换为文档类型数据 (HotelDoc)
3.利用avaRestClient中的Bulk批处理,实现批量新增文档,示例代码如下