一、整合ES
ES常用概念
索引,类型,文档是什么?
- 索引就像是Mysql中的库
- 类型就像是Mysql中的表
- 文档就像是数据
- 属性就是列名
- 所有的数据都是Json格式
倒排索引
简约理解版本2.0
正向索引,数据库创建索引,增加搜索速度。
倒排索引是根据关键字去找文档,然后记录一下出现的位置和次数。
根据关键字去找文档,然后记录一下出现的位置和次数
什么是倒排索引?
ElasticSearch中一个重要的概念 : 倒排索引(Inverted Index)也叫反向索引,有反向索引必有正向索引。通俗地来讲,正向索引是通过key找value,反向索引则是通过value找key。
首先弄懂几个概念,如果类比现代汉语词典的话,那么Term就相当于词语,Term Dictionary相当于汉语词典本身,Term Index相当于词典的目录索引,Posting List相当于词语在字典的页数集合:
- Term(单词):一段文本经过分析器分析以后就会输出一串单词,这一个一个的就叫做Term(直译为:单词)
- Term Dictionary(单词字典):顾名思义,它里面维护的是Term,可以理解为Term的集合
- Term Index(单词索引):为了更快的找到某个单词,我们为单词建立索引。B-Tree通过减少磁盘寻道次数来提高查询性能,
- Elasticsearch也是采用同样的思路,直接通过内存查找term,不读磁盘,但是如果term太多,term dictionary也会很大,放内存不现实,于是有了Term Index,就像字典里的索引页一样,A开头的有哪些term,分别在哪页,可以理解term index是一颗树:
- Posting List(倒排列表):倒排列表记录了出现过某个单词的所有文档的文档列表及单词在该文档中出现的位置信息,每条记录称为一个倒排项(Posting)。根据倒排列表,即可获知哪些文档包含某个单词。(PS:实际的倒排列表中并不只是存了文档ID这么简单,还有一些其它的信息,比如:词频(Term出现的次数)、偏移量(offset)等,可以想象成是Python中的元组,或者Java中的对象)
相关度分数score的计算
ES工作原理还是很复杂的,现阶段我们学会使用即可,到后期准备面试了,在继续深入学习!
安装ES和Kibana
快速安装
(1)下载ealastic search(存储和检索)和kibana(可视化检索) docker pull elasticsearch:7.4.2 docker pull kibana:7.4.2 (2)配置 # 将docker里的目录挂载到linux的/mydata目录中 # 修改/mydata就可以改掉docker里的 mkdir -p /mydata/elasticsearch/config mkdir -p /mydata/elasticsearch/data # es可以被远程任何机器访问 echo "http.host: 0.0.0.0" >/mydata/elasticsearch/config/elasticsearch.yml # 递归更改权限,es需要访问 chmod -R 777 /mydata/elasticsearch/ (3)启动Elastic search # 9200是用户交互端口 9300是集群心跳端口 # -e指定是单阶段运行 # -e指定占用的内存大小,生产时可以设置32G docker run --name elasticsearch -p 9200:9200 -p 9300:9300 \ -e "discovery.type=single-node" \ -e ES_JAVA_OPTS="-Xms64m -Xmx512m" \ -v /mydata/elasticsearch/config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml \ -v /mydata/elasticsearch/data:/usr/share/elasticsearch/data \ -v /mydata/elasticsearch/plugins:/usr/share/elasticsearch/plugins \ -d elasticsearch:7.4.2 # 设置开机启动elasticsearch docker update elasticsearch --restart=always (4)启动kibana: # kibana指定了了ES交互端口9200 # 5600位kibana主页端口 docker run --name kibana -e ELASTICSEARCH_HOSTS=http://192.168.1.8:9200 -p 5601:5601 -d kibana:7.4.2 # 设置开机启动kibana docker update kibana --restart=always
查看elasticsearch版本信息: http://192.168.1.8:9200
kibana
访问Kibana: http://192.168.1.8:5601/app/kibana
初步检索_cat
GET /_cat/nodes 查看所有节点。集群中会用到 GET /_cat/health 查看es健康状况 GET /_cat/master 查看主节点 GET /_cat/indices 查看所有索引 ,等价于mysql数据库的show databases;
ES的增删改查
新增文档
put新增
新增文档也就是新增数据库中的表,保存的时候用唯一的标识指定
http://192.168.1.8:9200/customer/external/1
post新增
不带id
带上id,也是新增修改二合一
区别
PUT必须指定id;由于PUT需要指定id,我们一般用来做修改操作
POST新增。如果不指定id,会自动生成id,指定存在的id为更新
查询文档
GET /customer/external/1
乐观锁的使用
通过“if_seq_no=1&if_primary_term=1”,当序列号匹配的时候,才进行修改,否则不修改。
开启事务锁后,两个事务并行修改数据的时候,只要有一个事务修改完数据,记录中记录的版本号就会加1,另一个事务修改的时候会带上版本号判断,如果版本号发生了变化了那就不会进行修改
更新文档_update
POST customer/externel/1/_update { "doc":{ "name":"111" } } 或者 POST customer/externel/1 { "doc":{ "name":"222" } }
不同:带有update情况下
- POST操作会对比源文档数据,如果相同不会有什么操作,文档version不增加。(带乐观锁)
- PUT操作总会重新保存并增加version版本(不带)
删除文档或索引
DELETE customer/external/1 DELETE customer
注:elasticsearch并没有提供删除类型的操作,只提供了删除索引和文档的操作。
ES的批量操作_bulk
执行多条数据
这些数据之间是相互独立的,一条失败,不会影响其他数据
kibana中执行 POST /customer/external/_bulk {"index":{"_id":"1"}} {"name":"John Doe"} {"index":{"_id":"2"}} {"name":"John Doe"} #! Deprecation: [types removal] Specifying types in bulk requests is deprecated. { "took" : 20, "errors" : false, "items" : [ { "index" : { "_index" : "customer", "_type" : "external", "_id" : "1", "_version" : 5, "result" : "updated", "_shards" : { "total" : 2, "successful" : 1, "failed" : 0 }, "_seq_no" : 10, "_primary_term" : 1, "status" : 200 } }, { "index" : { "_index" : "customer", "_type" : "external", "_id" : "2", "_version" : 1, "result" : "created", "_shards" : { "total" : 2, "successful" : 1, "failed" : 0 }, "_seq_no" : 11, "_primary_term" : 1, "status" : 201 } } ] }
样本测试数据
https://gitee.com/xlh_blog/common_content/blob/master/es%E6%B5%8B%E8%AF%95%E6%95%B0%E6%8D%AE.json#
ES进阶
https://www.elastic.co/guide/en/elasticsearch/reference/7.6/docs-reindex.html
官方文档如下:
如下示例看着文档就可以写出来。
两种查询方式
ES支持两种基本方式检索;
- 通过REST request uri 发送搜索参数 (uri +检索参数);
- 通过REST request body 来发送它们(uri+请求体);
测试如下:
GET bank/_search/?q=*&sort=account_number:asc 说明: q=* # 查询所有 sort # 排序字段 asc #升序 GET bank/_search { "query": { "match_all": {} }, "sort": [ { "account_number": "asc" } ] } 添加新的查询条件 GET bank/_search { "query": { "match_all": {} }, "sort": [ { "account_number": "asc" }, { "balance": "desc" } ] }
QueryDSL
QueryDSL就是我们第二种查询方式中请求体的内容
它的格式如下:
如果针对于某个字段,那么它的结构如下: { QUERY_NAME:{ # 使用的功能 FIELD_NAME:{ # 功能参数 ARGUMENT:VALUE, ARGUMENT:VALUE,... } } } GET bank/_search { "query": { # 查询的字段 "match_all": {} }, "from": 0, # 从第几条文档开始查 "size": 5, "_source":["balance"], #_source为要返回的字段 "sort": [ { "account_number": { # 返回结果按哪个列排序 "order": "desc" # 降序 } } ] }