目录
一、引言
1.1 海量数据
在海量数据中执行搜索功能时,如果使用MySQL,效率太低。
1.2 全文检索
在海量数据中执行搜索功能时,如果使用MySQL,效率太低。
1.3 高亮显示
将搜索关键字,以红色的字体展示。
二、ES概述
2.1 ES的介绍
ES是一个使用Java语言并且基于Lucene编写的搜索引擎框架,他提供了分布式的全文搜索功能,提供了一个统一的基于RESTful风格的WEB接口,官方客户端也对多种语言都提供了相应的API。
Lucene:Lucene本身就是一个搜索引擎的底层。
分布式:ES主要是为了突出他的横向扩展能力。
全文检索:将一段词语进行分词,并且将分出的单个词语统一的放到一个分词库中,在搜索时,根据关键字去分词库中检索,找到匹配的内容。(倒排索引)
RESTful风格的WEB接口:操作ES很简单,只需要发送一个HTTP请求,并且根据请求方式的不同,携带参数的同,执行相应的功能。
应用广泛:Github.com,WIKI,Gold Man用ES每天维护将近10TB的数据。
2.2 ES的由来
ES回忆时光 |
---|
![]() |
2.3 ES和Solr
Solr在查询死数据时,速度相对ES更快一些。但是数据如果是实时改变的,Solr的查询速度会降低很多,ES的查询的效率基本没有变化。
Solr搭建基于需要依赖Zookeeper来帮助管理。ES本身就支持集群的搭建,不需要第三方的介入。
最开始Solr的社区可以说是非常火爆,针对国内的文档并不是很多。在ES出现之后,ES的社区火爆程度直线上升,ES的文档非常健全。
ES对现在云计算和大数据支持的特别好。
zookeeper(动物管理员):分布式协调工具
2.4 倒排索引
将存放的数据,以一定的方式进行分词,并且将分词的内容存放到一个单独的分词库中。
当用户去查询数据时,会将用户的查询关键字进行分词。
然后去分词库中匹配内容,最终得到数据的id标识。
根据id标识去存放数据的位置拉取到指定的数据。
倒排索引 |
---|
![]() |
三、 ElasticSearch安装
3.1 安装ES&Kibana
docker-compose.yml文件
version: '2'
services:
elasticsearch:
image: elasticsearch:7.6.2
container_name: es
environment:
- discovery.type=single-node
networks:
- esnet1
ports:
- "9200:9200"
kibana:
image: docker.elastic.co/kibana/kibana:7.6.2
container_name: kibana
environment:
- elasticsearch_url=http://elasticsearch:9200
networks:
- esnet1
ports:
- "5601:5601"
networks:
esnet1:
安装出现的问题:
启动es最大虚拟内存不足:
#修改文件 vi /etc/sysctl.conf #设置ES最大虚拟内存大小 vm.max_map_count=655360 #让设置生效 sysctl -p启动es时,持久化数据的数据卷没有权限修改:
# 修改数据卷目录的权限 chmod 777 data启动kibana报错pid: "6":
# 进去kibana容器 docker exec -it kibana bash # 修改config目录下的kibana.yml vi config/kibana.yml # 将elasticsearch:9200替换为es容器的id地址:9200 # 将最后的true,改为false
# ** THIS IS AN AUTO-GENERATED FILE **
# Default Kibana configuration for docker target
server.name: kibana
server.host: "0"
elasticsearch.hosts: [ "http://你的地址:9200" ]
xpack.monitoring.ui.container.elasticsearch.enabled: false
3.2 安装IK分词器
进去到ES容器内部,跳转到 bin 目录下,执行 bin 目录下的脚本文件:
./elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.6.2/elasticsearch-analysis-ik-7.6.2.zip
重启ES的容器,让IK分词器生效。
浏览器访问Kabana:
你的地址:5601
-
使用Kabana测试Ik分词器效果:
POST _analyze
{
"analyzer": "ik_max_word",
"text": "中华人民共和国"
}
四、 ElasticSearch基本操作
4.1 ES的结构
ElasticSearch整体结构图:
4.1.1 索引Index,分片和备份
ES的服务中,可以创建多个索引。
每一个索引默认被分成5片存储。
每一个分片都会存在至少一个备份分片。
备份分片默认不会帮助检索数据,当ES检索压力特别大的时候,备份分片才会帮助检索数据。
备份的分片必须放在不同的服务器中。
一张表 对应 一个索引
表中的 一条记录对应 一个文档
表中一个字段对应一个 域
索引分片备份 |
---|
![]() |
4.1.2 类型 Type
一个索引下,可以创建多个类型。
类型 |
---|
![]() |
4.1.3 文档 Doc
一个类型下,可以有多个文档。这个文档就类似于MySQL表中的多行数据。
文档 |
---|
![]() |
4.1.4 属性 Field
一个文档中,可以包含多个属性。类似于MySQL表中的一行数据存在多个列。
属性 |
---|
![]() |
4.2 操作ES的RESTful语法
注意 : 我们是基于7.x版本的ElasticSearch, 所以没有type
GET请求:
http://ip:port/index:查询索引信息
http://ip:port/index/type/doc_id:查询指定的文档信息
POST请求:
http://ip:port/index/type/_search:查询文档,可以在请求体中添加json字符串来代表查询条件
http://ip:port/index/type/doc_id/_update:修改文档,在请求体中指定json字符串代表修改的具体信息
PUT请求:
http://ip:port/index:创建一个索引,需要在请求体中指定索引的信息,类型,结构
http://ip:port/index/type/_mappings:代表创建索引时,指定索引文档存储的属性的信息
DELETE请求:
http://ip:port/index:删除索引
http://ip:port/index/type/doc_id:删除指定的文档
4.3 索引的操作
4.3.1 创建一个索引
语法如下
# 创建一个索引, person是索引名字, shards主分片是5片, replicas是备份分片1片
PUT /person
{
"settings": {
"number_of_shards": 5,
"number_of_replicas": 1
}
}
-
执行完上面语法, 在下面这里可以查询到已经创建好的person索引结构:
4.3.2 查看索引信息
语法如下
# 查看索引信息
GET /person
4.3.3 删除索引
语法如下
# 删除索引
DELETE /person
4.4 ES中Field可以指定的类型
字符串类型:
text:一般被用于全文检索。 将当前Field进行分词。
keyword:当前Field不会被分词。
数值类型:
long:取值范围为-9223372036854774808~922337203685477480(-2的63次方到2的63次方-1),占用8个字节
integer:取值范围为-2147483648~2147483647(-2的31次方到2的31次方-1),占用4个字节
short:取值范围为-32768~32767(-2的15次方到2的15次方-1),占用2个字节
byte:取值范围为-128~127(-2的7次方到2的7次方-1),占用1个字节
double:1.797693e+308~ 4.9000000e-324 (e+308表示是乘以10的308次方,e-324表示乘以10的负324次方)占用8个字节
float:3.402823e+38 ~ 1.401298e-45(e+38表示是乘以10的38次方,e-45表示乘以10的负45次方),占用4个字节
half_float:精度比float小一半。
scaled_float:根据一个long和scaled来表达一个浮点型,long-345,scaled-100 -> 3.45
时间类型:
date类型,针对时间类型指定具体的格式
布尔类型:
boolean类型,表达true和false
二进制类型:
binary类型暂时支持Base64 encode string
范围类型:
long_range:赋值时,无需指定具体的内容,只需要存储一个范围即可,指定gt,lt,gte,lte
integer_range:同上
double_range:同上
float_range:同上
date_range:同上
ip_range:同上
经纬度类型:
geo_point:用来存储经纬度的
ip类型:
ip:可以存储IPV4或者IPV6
小结 :常用需要记住的内容如下 :
-
字符串类型:
-
keyword:不能被分词
-
text:可以被分词
-
-
数值类型:
-
整形:byte,short,integer,long
-
浮点型:float,double
-
-
时间类型:
-
date:可以给date类型指定format格式化,支持时间戳以及年月日等格式
-
-
IP类型:
-
存储ip
-
-
GEO_POINT类型:
-
存储经纬度
-
Ps官网文档:Field datatypes | Elasticsearch Guide [7.6] | Elastic
4.5 创建索引并指定数据结构
语法如下
# 创建索引,指定数据结构
PUT /book
{
"settings": {
# 分片数
"number_of_shards": 5,
# 备份数
"number_of_replicas": 1
},
# 指定数据结构
"mappings": {
# 类型 Type, 我们是7.x版本, 所以没有这个novel, 直接写下面properties数据就可以。
"novel": {
# 文档存储的Field
"properties": {
# Field属性名
"name": {
# 类型
"type": "text",
# 指定分词器
"analyzer": "ik_max_word",
# 指定当前Field可以被作为查询的条件
"index": true ,
# 是否需要额外存储
"store": false
},
"auth": {
"type": "keyword"
},
"count": {
"type": "long"
},
"createtime": {
"type": "date",
# 时间类型的格式化方式
"format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis"
},
"desc": {
"type": "text",
"analyzer": "ik_max_word"
}
}
}
}
}
-
下面是正确的存放书籍信息数据索引结构 :
PUT /book
{
"settings": {
"number_of_shards": 5,
"number_of_replicas": 1
},
"mappings": {
"properties": {
"name": {
"type": "text",
"analyzer": "ik_max_word",
"index": true,
"store": false
},
"auth":{
"type": "keyword"
},
"count":{
"type": "integer"
},
"createtime":{
"type": "date",
"format": "epoch_millis||yyyy-MM-dd||yyyy-MM-dd HH:mm:ss"
},
"desc":{
"type": "text",
"analyzer": "ik_max_word"
}
}
}
}
4.6 文档的操作
文档在ES服务中的唯一标识,
_index
,_type
,_id
三个内容为组合,锁定一个文档,操作是添加还是修改。
4.6.1 新建文档
自动生成_id
# 添加文档,自动生成id
POST /book/_doc
{
"name": "盘龙",
"auth": "我吃西红柿",
"count": 100000,
"createtime": "2000-01-01",
"desc": "山重水复疑无路,柳暗花明又一村"
}
手动指定_id
# 添加文档,手动指定id
PUT /book/_doc/1
{
"name": "红楼梦",
"auth": "曹雪芹",
"count": 4353453,
"createtime": "1985-01-01",
"desc": "一个是阆苑仙葩,一个是美玉无瑕"
}
4.6.2 修改文档
覆盖式修改
# 添加文档,手动指定id
PUT /book/_doc/1
{
"name": "金瓶梅",
"auth": "古人",
"count": 4353453,
"createtime": "1985-01-01",
"desc": "讲述潘金莲,李瓶,春梅的爱情故事!"
}
doc修改方式
# 修改文档,基于doc方式
POST /book/_update/1
{
"doc": {
"name":"斗破苍穹"
}
}
4.6.3 删除文档
根据id删除
# 根据id删除文档
DELETE /book/_doc/2