一个分布式的开源搜索和分析引擎,可以 秒 级的从海量数据中检索
主要功能:做数据的检索和分析(MySQL专攻于数据的持久化存储与管理CRUD达到百万以上的数据MSQL就会很慢,海量数据的检索和分析还是要用ElasticSearch)
用途:我们电商项目里的所有的检索功能都是由ElasticSearch完成的
底层:开源库 Lucene ,然后对 Lucene 进行封装,提供了 REST API 接口,开箱即用
REST API: 天然的跨平台
版本对应:
类比MySQL:
1.动词:类似于MySQL的insert: 创建一条数据在 ElasticSearch 里叫 索引一条数据
2.名词:类似于MySQL的Database
在 Index 中可以定义一个或者多个 Type
类似于MySQL 数据库 和 表 的关系:MySQL里叫在某个数据库的某张表里,在ES里叫某个索引的某个类型下
已经没有type了 现在索引就是表 索引还有映射 然后索引库里边存的就是文档了.......
保存在某个索引(Index)下,某种类型(Type)的一个数据(Document),文档是JSON格式的,Document就像是 MySQL中的某个Table 里面的内容;
比如我们保存一条记录:红海行动
ES会先把 红海行动 进行分词,比如分成 红海 和 行动 两个单词,除了存入1号记录 红海行动 这个文档之外,额外又维护了一张 倒排索引表 :倒排索引表就会存 红海 1,行动 1,两个文档
然后我们再来保存2号记录 探索红海行动
先分词成: 探索 红海 行动 ,先存入2号记录 探索红海行动 ,再额外维护 倒排索引表 更新 红海 和 行动的记录 加入 探索 的记录 :红海 1,2 和 行动 1,2 和 探索 2
以此类推....
然后当我们检索时 输入 红海特工行动 它也会分词成为 红海 特工 行动 三个单词,然后会从倒排索引表里找到 红海 特工 行动 这三个词的记录 就会查到 12345条记录,但是哪一个才是更贴和我们的搜索目标呢,引入一个相关性得分(比如3号记录共有3个单词命中了两个,相关性得分2/3),我们就会根据相关性得分从高到低排序
在CentOS 7上安装和配置Elasticsearch的方法_centos7搭建elasticsearch-CSDN博客
然后要在elasticsearch.yml上添加这个配置: http.host: 0.0.0.0
然后安装kibana:
参考这个博主:
CentOS 7 上安装 Kibana 7.12.1_kibana 7.12.1 license-CSDN博客
做完这两个博主的内容就能跳过视频P104
因为封装成 REST API,我们直接使用APIfox发请求就能用
GET/_cat/nodes:查看所有节点
GET/_cat/health:查看 es 健康状况
GET/_cat/master:查看主节点
GET/ cat/indices:查看所有索引 相当于MySQL里的show databases;
因为ES8以后不能创建多个type所以我们用到的请求是
emmmES7应该只是化了type的概念,跟着视频里应该也可以,因为我们这里装的是7.9.2的ES
我建议还是使用post发/_doc吧,以后会慢慢更新淘汰掉视频里的语法的
视频中的方法:
POST:
乐观锁,当他们并发发送请求的时候,可以加上判断条件if_seq_no=3,当seq_no=3时才能操作成功,且成功后seq_no会改变,当另一条请求也带上判断条件if_seq_no=3时,操作就会失败
模拟并发更改:
同时对id为1的数据发送put请求更改name:
当第一条请求带上乐观锁操作发出去且seq_no=3时
此时再发送第二条请求也带上乐观锁操作让seq_no=3时:
POST:
当带了_update 语法一定要带上 doc
_update会对比原数据,如果本次传的数据和原数据一模一样,版本号就不会加,操作就是noop(没有操作),序列号(_seq_no)也不变
不带_update 语法不加 doc://等同于PUT不加_update
不会检测原数据直接更新,版本号,序列号都会加
必须发POST请求
来到Kiana
批量保存测试数据:
es测试数据.json · 坐看云起时/common_content - Gitee.com
ES 支持两种基本方式检索
一个是通过使用 REST request URl 发送搜索参数(uri+检索参数)
另一个是通过使用 REST requestbody 来发送它们(uri+请求体)
"_source":["name","age"],只返回name和age字段
match,条件查询指定的是一个非字符串的属性,就是精确查询
当指定的是字符串的属性就是模糊查询:(全文检索)(倒排索引),最终会按照评分去进行排序,会对检索的字符串进行分词
对字符串不进行分词(精确查询)
must:必须满足,
must_not:必须不满足
should:应该,满足最好,不满足也行(满足了加评分,会排在前面)
不会贡献文档的相关性得分
不用filter:
用了filter
类似于match,term用来找精确值字段,例如age
match用来全文检索,字符串模糊查询用,例如address
文本用match,数字用term
另外,区别 match_phrase 和 属性名.keyword :
分析和检索是一次性的:一次请求过去,我们既能查出数据,也能把数据分析到位
例如需求是:搜索 address 中包含 mill 的所有人的年龄分布以及平均年龄,但不显示这些人的详情。
先看看查出所有 address 中包含 mill 的所有人, 并列举出他们的年龄分布
再加一个平均值聚合
如何不看这些人的详细信息呢,我们让size=0,就可以只看聚合结果:
进阶:子聚合 按照年龄聚合,并且请求这些年龄段的这些人的平均薪资
就可以查到如下结果:
再进阶:查出所有年龄分布,并且这些年龄段中M(男)的平均薪资和F(女)的平均薪资以及这个年龄
段的总体平均薪资
定义一个文档如何被进行处理的:例如我们可以定义那个string类型的字段是可以被当作全文检索的
像是创建SQL表时定义每一列数据类型是什么
ES会在第一次保存数据的时候自动猜测数据类型
就是每一个文档的数据类型是什么
我们可以查看mapping信息
我们也可以在创建索引时指定映射(有很多类型,可以参考文档)
1.添加新的字段映射:
2.修改已经存在的字段
对于已经存在的映射字段,我我们是不能更新的
3.数据迁移
因为映射不支持修改,我们想要修改,能用的办法就是新建一个映射字段,把数据迁移进去:
先创建一个新索引
下一步数据迁移:
这是没有type的写法
一个 tokenizer(分词器) 接收一个字符流,将之分割为独立的 tokens(词元,通常是独立的单词),然后输出 tokens 流。例如,whitespace tokenizer遇到空白字符时分割文本。它会将文本"Quick brown fox!"分割为 [Quick, brown, fox!]。
该 tokenizer(分词器) 还负责记录各个term(词条) 的顺序或 position 位置(用于 phrase 短语和 word proximity词近邻查询),以及 term(词条)所代表的原始word(单词)的 start(起始)和 end(结束)的 characteroffsets(字符偏移量)(用于高亮显示搜索的内容)。
Elasticsearch提供了很多内置的分词器,可以用来构建custom analyzers(自定义分词器)
为虚拟机的elasticsearch装ik分词器:
找到Releases · infinilabs/analysis-ik · GitHub对应的版本(我用的7.9.2)
解压放在ik文件夹里放进plugins目录下,重启elasticsearch服务
测试分词:
创建自定义词库:
下载nginx:
CentOS7下安装NGINX_centos7下载nginx-CSDN博客,跟着这个步骤来,记得开防火墙的80端口,然后在/usr/local/nginx/html这个路径下新建es文件夹,fenci.txt,会出现乱码问题,后续解决;
配置ik分词器的远程词库地址:
来到ik的config文件夹:
至此,新词就可以添加进/usr/local/nginx/html/es文件夹下的fenci.txt
新建模块:
修改配置文件,添加依赖:
新建config包,
添加common依赖,配置nacos注册中心:
启用服务注册发现:
引入ElasticSearch-Rest-Client的步骤;
1.在pom文件里导入依赖
2.给容器中注入一个RestHighLevelClient
3.参照官方API进行操作:Java High Level REST Client | Java REST Client [7.17] | Elastic
RequestOptions:请求设置项:
开始测试:
1.index:(保存更新都可以)
2.复杂检索:
1.先构造一个检索请求searchRequest
2.构造检索条件:
query条件构造:
聚合条件构造:嵌套使用 .subAggregation()
获取查询结果:
获取分析数据: