一. ElasticSearch介绍
1.1 引言
- 在海量数据中执行所有功能时候,使用MySQL,效率太低
- 如果输入的关键字不准确,同样可以搜索到数据
- 将搜索的关键字,以红色字体显示
1.2 ES的介绍
ES是使用Java语言,基于Lucene的全文检索框架,实现分布式全文检索的功能,提供基于RESTful风格的WEB接口;官方也为各种语言通过的API
Lucene:本身就是全文检索的底层
分布式:主要是为了突出他的横向扩展功能(搭建集群)
全文检索:分词器(将一段词语进行分词,统一放到分词库中,在检索时候,根据关键词从分词库中检索,找到匹配的内容)+倒排查找
RESTful风格的WEB接口:只需要发送一个HTTP请求,根据请求方式的不同,携带参数的不同,执行相应的功能
1.3 ES和Slor
1. Slor在查询死数据的时候比ES的效率快,但是查询实时数据的时候,Slor的查询速度会降低很多而ES基本没有什么变化
2. Slor的搭建基于Zookeeper来管理,ES本身就支持集群的搭建,不需要第三方的框架
3.
1.4 倒排索引
二.ElasticSearch安装
2.1 安装ES&Kibana
1 | version: '3.1' |
2.2 安装IK分词器
安装步骤: 安装结束之后,需要重启elasticsearch
1 | docker ps |
测试:
1 | POST _analyze |
三.ElasticSearch基本操作
ES的结构
索引 Index
ES服务可以创建多个索引Index
每个索引Index默认分成五个分片,每个分片存在至少一个备份分片,
默认备份分片不会参与检索,当主分片压力过大时候才会参与检索
备份的分片必须放在不同的服务中
类型Type
一个索引Index下可以创建多个类型Type
根据版本不同,类型Type的创建也会不同
文档 doc
一个类型Type下,可以创建多个文档doc
这个文档类似于MySQL表中的多行数据
属性 field
一个文档doc中,可以包含多个属性filed
类似于MySQL表中一行数据存在多个列
image-20201004094905540
3.2 操作ES的RESTful语法
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/do_id/_update_可以在请求体中添加json字符串代表修改的信息
PUT请求:
创建索引:http://ip:port/index/ 可以在请求体重添加json字符串,指定索引的信息、类型、结构
创建索引的时,指定索引文档存储的属性信息:http://ip:port/index/type/type/_mappings_
DELETE请求:
删除指定的文档:http://ip:port/index/type/doc_id
3.3 索引ndex的操作
3.3.1 创建一个索引
1 | #创建一个索引 |
3.3.2 查看一个索引
1 | # 查看索引信息 |
3.3.3 删除索引Index
1 | # 删除索引 |
3.4 ES中field可以指定的类型
String 类型
text: 一般被用于全文检索,(商品的描述),可以将当前的filed进行分词
keyword:当前的field不会被分词
数值类型:
- long:
- integer:
- short:
- double:
- float:
- half_float:精度比float小一半
- scaled_float:根据一个long类型和指定的scaled来表达浮点型,long 345 sacled 100 表达 3.45
时间类型
- date类型:根据时间类型指定具体的格式
布尔类型
- boolean类型:表达true和false
二进制类型:
- binary:基于64位 encode string
范围类型
- long_range:赋值时候无需指定具体的内容,只需要存储一个范围就行,例如 gt,lt,gte,lte
- float_range:
- Integer_range:
- double_range:
- date_range:
- ip_range:
GEO经纬度类型
- geo_point:用来存储经纬度
IP类型
- ip:存储ipv4和ipv6
其他的数据类型参考官网
https://www.elastic.co/guide/en/elasticsearch/reference/6.5/mapping-types.html
3.5 创建索引Index并指定数据结构(field)
1 | # 创建索引 指定数据结构 |
3.6 文档的操作
文档在ES服务中的唯一标识, ‘-index’, ‘-type’, ’_id’ 为组合锁定一个文档,来区分操作是添加还是修改
3.6.1 新建文档
‘自动生成id’
1 | #添加文档,自动生成ID |
‘手动指定id’
1 | #添加文档,手动指定id |
3.6.2 修改文档
‘覆盖式修改’
1 | #覆盖式修改,如果id存在,则会覆盖,否则新建 |
‘doc修改方式’
1 | #修改文档,基于doc |
3.6.3 删除文档
‘根据id删除文档’
1 | #根据id删除文档 |
四.Java操作ElasticSearch
4.1 Java连接ES
创建maven项目
添加依赖
- elasticsearch
- elasticsearch高级API(REST High Level)
- lombok
- Junit
1 | <!-- elasticsearch的依赖 --> |
连接ES,创建测试类
1 | package space.wuchao.distribution.common.utils; |
1 | package space.wuchao.distribution.elasticsearch; |
4.2 索引操作
4.2.1 Java创建索引并指定数据结构field
1 | package space.wuchao.distribution.elasticsearch; |
4.2.2 检查索引是否存在,删除索引
‘检查索引是否存在’
1 | /** |
‘删除索引操作’
1 | /** |
4.3 文档操作
4.3.1添加文档操作
1 | /** |
4.3.2 修改文档
1 | /** |
4.3.3 删除文档doc
1 | /** |
4.4 批量操作Doc
4.1.1 批量添加
1 | /** |
4.4.2 批量删除
1 | /** |
五.ElasticSearch练习
‘创建索引index’
1 | String index = "sms-logs-index"; |
‘创建文档doc,添加数据’
1 | /** |
六.ElasticSearch各种查询
6.1 term & terms 查询
6.1.1 term查询
term查询是完整查询,搜索之前不会对关键字进行分词,直接用搜索的关键字分词库中去查询,得到结果。
- json格式
1 | # term 查询 |
- Java代码
1 | /** |
当term查询时候,如果查询的关键字对应的filed的type不是keyword,而是text,则doc中的数据已经被分词,需要关键字与doc中经过分词后的值一致才可以查到结果。即使关键字对应field的type是keyword,如果关键字与doc中的值不完全一致也会查不到结果
‘示例’
1 | # corpName field的type为text,当关键字为“滴滴打车”时,并不能查询到结果 |
‘示例二:’
1 | # 当field的type类型为keyword的时候,关键字与doc中的不一致,也查询不到结果 |
6.1.2 terms查询
terms与term查询的机制一样,不会将查询的关键字进行分词,而是去分词库中直接去匹配,找到相应的doc内容
terms是在针对一个字段包含多个值的情况下使用
term:where province=“北京”
terms:where province=“北京” or province = “另一个值”
‘Json格式’
1 | # terms查询 |
‘Java实现’
1 | /** |
6.2 match查询
match查询是高层查询,根据查询字段的数据类型的不同,采用不同的查询方式。
- 查询的是日期或者是数值的话,match会将你给的字符串查询内容转换成日期格式或者是数值格式。
- 如果查询的内容是一个不能被分词的内容(keyword),match查询不会对你指定的查询关键字进行分词。
- 如果查询的内容是一个可以被分词的内容(text),match查询会将你个查询的关键字根据一定的方式去分词,去分词库中匹配查询的内容。
match查询,实际上底层是多个term查询,将多个term查询的结果封装到一起
6.2.1 match_all查询
‘Json格式’
1 | #match_all查询 |
‘Java代码实现’
1 | /** |
6.2.2 match查询
‘Json格式’
1 | #match 查询 |
‘Java实现’
1 | /** |
6.2.3 布尔match查询
对一个field采用and或者or连接来匹配内容
‘Json格式’
1 | #布尔match查询 |
‘or查询’
1 | POST /sms-logs-index/sms-logs-type/_search |
‘Java代码实现’
1 | /** |
6.2.4 multi_match查询
match 查询针对一个field查询,multi_match查询是针对多个field查询 多个field对应多个text
‘Json格式’
1 | #multi_match查询 |
‘Java代码实现’
1 | /** |
6.3 其他查询
6.3.1 id 查询
id查询,类似于MySQL中的 where id = ?
‘json格式查询’
1 | #id查询 |
‘Java代码实现’
1 | /** |
6.3.2 ids查询
ids查询类似于MySQL中的 where id in (id1, id2, id3 …….)
‘Json格式实现’
1 | #ids查询 |
‘Java代码实现’
1 | /** |
6.3.3 prefix查询
前缀查询,可以通过一个关键字作为field的前缀,来查询指定的文档
‘Json格式查询’
1 | #prefix查询 |
‘Java代码实现’
1 | /** |
6.3.4 fuzzy查询
模糊查询,输入一个模糊的关键字,ES就可以根据输入的关键字大概去匹配一个结果。查询结果不太稳定
可以指定前几个字符不能有错 prefix_length来指定
‘Json格式查询’
1 | POST /sms-logs-index/sms-logs-type/_search |
‘Java代码实现’
1 | /** |
6.3.5 wild_card查询
wild_card查询:通配查询,和MySQL中的like是一个套路,可以在查询中,在关键字中指定通配符*和占位符?
‘Json实现’
1 | #wild_card查询 |
‘Java代码实现’
1 | /** |
6.3.6 range查询
范围查询,只针对数值类型,对某一个field进行大于或者小于的范围查询
‘Json查询’
1 | #range查询 |
‘Java查询’
1 | /** |
6.3.7 regexp查询
正则查询 通过你编写的正则表达式去匹配内容
prefix、fuzzy、wildcard、regexp查询效率相对比较低,要求效率时候,尽量避免使用这几种查询方式
‘Json格式查询’
1 | #regezp 查询 正则查询 |
‘Java查询’
1 | /** |
6.4 深分页查询 Scroll查询
ES对from+size分页是有限制的 from+size的之和不能超过一万
原理:
from+size ES查询数据的方式:
- 先将用户指定的关键字进行一个分词。
- 将分词后的关键字在分词库中检索,获取到文档doc的id
- 去各个分片中拉取指定的数据, 查询时间比较长
- 将查询的到的数据按着一定的规律score进行排序
- 根据from的值,将查询到的数据舍弃一部分
- 返回结果
Scroll+size 在ES查询数据的方式:
- 先将用户指定的关键字进行分词
- 将分词后的关键字在分词库中检索,获取文档doc的id
- 将查询到的数据放入到ES的上下文中
- 根据size的个数在ES中查询指定个数的数据,同时在ES的上下文中删除已查询到的数据的id
- 如果要查询下一页数据,从ES上下文中找后续的数据,循环执行,知道上下文中的数据被全部取出
- 循环第四步和第五步,返回结果
Scroll查询方式,不能查询实时数据
‘Json格式查询’
1 | #Scroll查询,返回第一页数据,将scroll_id存储在ES的上下文中,并且指定id的存活时间 |
‘Java代码查询’
1 | /** |
6.5 delete-by-query查询
将根据关键字查询出的数据删除,删除过程也是查询一条符合条件的,删除一条。
如果删除数据是index中的大部分的数据,不推荐使用delete-by-query;只需要重新创建一个index,将要保留的数据复制到新的index中。
‘Json格式’
1 | # delete-by-query |
‘Java代码实现’
1 | /** |
6.6 复合查询
6.6.1 bool查询
复合过滤器,将你的多个查询条件根据一定的逻辑组合在一起
- must:所有的条件,用must组合在一起就是AND的意思
- must_not:全部都不能匹配,标识NO的意思
- should:将所有条件用should组合在意思,标识OR的意思
‘Json格式实现’
1 | #复合查询 bool查询 |
‘Java代码实现’
1 | /** |
6.6.2 boosting查询
boosting查询 可以帮助我们去影响查询后的score
- positive:只有匹配上positive的查询结果,才会被放在返回的结果集中
- negative:如果匹配上和positive并且也匹配上negative,就可以降低这样的文档的score
- negative_boost:指定系数,必须小于1.0
关于查询时,分数是如何计算的
- 搜索的关键字在文档中出现的频次越高,分数越高
- 指定的文档内容越短,分数就越高
- 我们在搜索时,指定的关键字也会被分词,这个分词的内容,被分词库匹配的个数越多,分数越高
‘Json实现’
1 | # 复合查询 boosting查询 |
‘Java代码实现’
1 | /** |
6.7 filter查询
query查询: 根据你的查询条件,去计算文档的匹配度,得到一个分数,并且根据分数进行拍讯,不会做缓存
filter查询:根据你的查询条件去查询文档,不去计算分数,filter会对经常被过滤的数据进行缓存
‘Json格式’
1 |
|
‘Java代码实现’
1 | /** |
6.8 HightLight 高亮查询
将客户输入的关键字,以一定的特殊样式展示给用户,让用户知道为什么这个结果被检索出来
高亮展示的数据,本身就是doc中的field,单独将field以hightlight的形式返回,不会影响原来的显示结果
ES提供了一个hightlight属性,与query同级别的
- fragment_size:指定高亮数据展现的字符个数 默认是100个
- pre_tags:指定前缀标签 例如:
- post_tags:指定后缀标签 例如:
‘Json格式实现’
1 |
|
‘Java代码实现’
1 | RestHighLevelClient client = ESClient.getClient(); |
6.9 聚合查询
ES的聚合查询比MySQL的聚合查询更强大,ES提供的统计数据的方式多种多样,
‘RestFul语法格式’
1 | POST /index/type/_search |
6.9.1 去重计数查询
去重计数,也就是cardinality
- 第一步,先将返回的文档中的一个指定的field进行去重。
- 第二步,然后统计一共有多少条
‘Json格式实现’
1 | #聚合查询之去重计数查询 cardinality |
‘Java代码实现’
1 |