一.ElasticSearch 简介:(102~102)
1.介绍:
1)Elasticsearch 解释:
-1:elastic:有弹力的、可伸缩、灵活
-2:search:查询
-3:ElasticSearch:是一个【开源的、高扩展到、分布式的、RESTful 风格的全文搜索引擎】,能够解决不断涌现出的各种用例。
1)Elasticsearch 和 Solr:区别?如何选择?
1)全文搜索:属于最常见的需求,开源的 Elasticsearch 是目前,全文搜索引擎的首选。
2)它可以快速的存储、搜索、和分析,海量的数据。
3)Elastic 是对 Lucene 的封装,提供了 RESTful 风格API 的操作接口。开箱即用。
4)官网:
-1:官网文档:https://www.elastic.co/guide/en/elasticsearch/reference/current/index.html
-2:官网中文:https://www.elastic.co/guide/cn/elasticsearch/guide/current/index.html
2.用途:
3.基本概念:
1)索引(Index)
动词:相当于 Mysql 中的 insert。
名次:相当于 Mysql 中的 DataBase(数据库)。
-1:索引是 Elasticsearch 对逻辑数据的逻辑存储,所以它可以分为更小的部分。
-2:可以把索引,看成关系型数据库的表,索引的结构,是为快速有效的全文索引准备的,特别是它不粗处原始值。
-3:Elasticsearch 可以把索引,存放在一台机器,或者分散在多台服务器上。
-4:每个索引可以有一个或多个分片(shard),每个分片可以有多个副本(replica)。
2)类型(Type)(7.x 版本,已经废弃使用,默认类型为:_doc )
在 Index(索引) 中,可以定义 一个/多个 Type(类型)。
类似于 Mysql 中的 Table,每一种类型的数据库,放在一起。
3)文档 (Document)
保存在 某个索引(index)下,某种类型(Type)下的一个数据(Document)。
文档是 JSON 格式的。文档就像是,Mysql 中的某个 Table 里面的数据。
-1:存储在 Elasticsearch 中的,主要实体叫文档。用关系型数据库来类比的话,一个文档相当于数据库表中的一行记录。
-2:Elasticsearch 和 MongoDB 中的文档类似,都可以有不同的结构,但 Elasticsearch 的文档只能够,相同字段必须有相同的类型。
-3:文档由 多个字段组成,每个字段可能多次出现在一个文档里,这样的字段叫 多值字段(multivalued)。
-4:每个字段的类型,可以是文本、数值、日期等。字段类型也可以是复杂类型,一个字段包含其他子文档 或者 数组。
4)映射(mapping)
-1:所有文档,写进索引之前,都会先进行分析,如何将输入的文本分割为词条、哪些词条又会被过滤,这种行为叫做映射。
-2:一般由用户自己定义规则。
5)文档类型
-1:在 Elasticsearch 中,一个索引对象,可以存储很多不同用途的对象。例如,一个博客应用程序,可以保存文章和评论。
-2:每个文档,可以有不同的结构。
-3:不同的文档类型,不能为相同的属性值,设置不同的类型。例如:在同一索引中的所有文档类型中,一个叫 title 的字段,必须具有相同的类型。
6)分片:
7)副本(Replicas):
8)图示:
4.检索原理:(倒排索引机制)
5.工作原理(官网)
6.索引是什么(官网)
7.LogStach 用途是什么(官网)
二.ElasticSearch 安装(103~104):
1.Docker 安装:
// 安装 Elasticsearch(存储和检索数据)
docker run -d \
-p 9200:9200 -p 9300:9300 \
--name es \
-e "discovery.type=single-node" \
elasticsearch:7.4.2
// 安装 Kibana(可视化检索数据)
docker run -d \
--name kibana \
-e ELASTICSEARCH_HOSTS=http://192.168.124.12:9200 \
-p 5601:5601 kibana:7.4.2
// 安装教程:
https://www.jianshu.com/p/ac3cf42dc95e
2.Linux 单节点部署
1)软件下载(7.11.1):https://www.elastic.co/cn/downloads/elasticsearch
2)安装:
-1:解压软件:
// 解压缩
tar -zxvf elasticsearch-8.0.0-linux-x86_64.tar.gz
-2:创建用户(因为安全问题,ES 不可用 root 用户运行使用)
-- 创建新的用户
useradd es // 新增 es 用户
passwd es // 为 es用户设置密码 (设置为了 es)
userdel -r es // 如果错了,可以删除再添加
chown -R es:es /usr/local/elasticsearch/elasticsearch-7.11.0 // 文件夹所有者
-3:修改配置文件:vim /config/elasticsearch.yml
17 cluster.name: my-centos-01-elasticsearch-name -- 识别集群到名女==名称
23 node.name: node-1
33 path.data: /usr/local/elasticsearch/elasticsearch-7.11.1/data -- 提前建好 数据目录
37 path.logs: /usr/local/elasticsearch/elasticsearch-7.11.1/logs -- 提前建好 日志目录
57 node.master: true -- 是不是有资格 选举 主节点
58 node.data: true -- 是不是有资格 选举 data 节点
56 network.host: 192.168.31.136 -- 本机ip
61 http.port: 9200
73 cluster.initial_master_nodes: ["node-1", "node-2"]
-4:修改配置文件:(末尾添加)vim /etc/security/limits.conf
-- 原因:es文件比较大,避免出现问题
-- 操作:设置每个进程,可以打开的文件数限制(打开的文件描述符的最大数目)
* soft nofile 65536
* hard nofile 65536
-- 解释:
-- soft 指的是当前系统生效的设置值(警告)
-- hard 表明系统中所能设定的最大值(错误)
-- soft 的限制不能比hard 限制高
-5:修改配置文件:(末尾添加)vim /etc/sysctl.conf
-- 更改一个进程能拥有的,最大最大内存区域限制
vm.max_map_count=655360
-- 禁用交换区
vm.swappiness=1
-6:重新加载:
sysctl -p
-7:修改配置文件:(末尾添加)vim /etc/security/limits.d/20-nproc.conf
-- 原因:es文件比较大,避免出现问题
-- 操作:设置每个进程,可以打开的文件数限制
7 es soft nofile 65536
8 es hard nofile 65536
-- 操作系统级别,对:每个用户创建的进程数的限制
* hard nproc 4096
-- 注:* 代表 Linux 所有用户名称
3)启动软件,访问测试:http://192.168.124.11:9200/
su es -- 不可使用 root 用户启动运行
cd /opt/elasticsearch/elasticsearch-8.0.0 -- 进入目录
/bin/elasticsearch -- 启动
/bin/elasticsearch -d -- 后台启动
3.Linux 集群部署
1)软件下载:同上
2)集群节点(4种):Elasticsearch 集群,是由多个节点组成,通过:
1、cluster.name:设置集群名称,并且用于区分其他的集群。
2、node.name:每个节点,通过 node.name,指定节点的名称。
-1:master 节点:
1、配置文件中的 node.master 属性,设置为 true(默认为:true),就有资格被选为 master 节点。
2、master 节点,用于控制整个集群的操作。比如:创建或删除索引、管理其他非 master 节点等。
-2:data 节点:
1、配置文件中 node.data 属性,设置为 true(默认为:true),就有资格被设置成 data 节点。
2、data 节点,主要用于执行数据相关的操作。比如文档 CRUD。
-3:客户端节点:
1、配置文件中,node.master 属性 和 node.data 属性均为:false。则该节点为:客户端节点。
2、该节点不能作为 master 节点,也不能作为 data 节点。
3、可以作为客户端节点,用于响应用户的请求,把请求转发到其他节点。
-4:部落节点:(连接其他集群)
1、当一个节点,配置 tribe.* 的时候,它就是一个特殊的客户端。
2、它可以连接多个集群,在所有连接的集群上,执行搜索和其他操作。
3)搭建集群,软件安装:
-1:解压缩
-- 解压缩
tar -zxvf elasticsearch-7.11.0-linux-x86_64.tar.gz
-- 重命名
mv elasticsearch-7.11.0 es-cluster-01
-- 关闭防火墙
systemctl stop firewalld
-2:将软件分发到其他节点:(centos_02,centos_03)
1、xsync es-cluster
2、scp -r es-cluster elsearch@192.168.40.124:/usr/local/elasticsearch
-3:创建用户:因为安全问题,ES 不允许 root 用户直接运行
-- 新增 es 用户
useradd es
-- 为 es 用户设置密码
passwd es
-- 如果错了,可以删除用户,再次添加
userdel -r es
-- 改变文件夹所有者
chown -R es:es /usr/local/elasticsearch/es-cluster/
-4:修改配置文件:vim /usr/local/elasticsearch/es-cluster/config/elasticsearch.yml
-- 加入如下配置
17 cluster.name: cluster-es -- 集群名称(集群中保持一致)
23 node.name: node-1 -- 节点名称,每个节点的名称,不能重复(node-2,node-3)
// (0.0.0.0)为任意网络均可访问。(或设置为本机 ip)
// 在此设置为本机 ip 地址,每个节点的 ip 地址不能重复
55 network.host: 192.168.124.11
57 node.master: true -- 是不是有资格 选举 主节点
58 node.data: true -- 是不是有资格 选举 data 节点
59 http.port: 9200 -- 访问端口
// **** 以下2个,设置会报错****(集群中不做配置,会和 “initial_master_nodes” 冲突)
// 设置发现集群广播的地址
-- 68 discovery.zen.ping.unicast.hosts: ["192.168.124.11","192.168.124.12","192.168.124.13"]
// 设置成为 master 节点的最小节点数(目前3个节点,2个同意可成为主节点)
// 很重要,否则会产生 “脑裂问题”。 = N/2 +1
69 discovery.zen.minimum_master_nodes: 2
// head 插件,需要打开这两个配置(跨域)
64 http.cors.allow-origin: "*"
65 http.cors.enabled: true
66 http.max_content_length: 200mb
// es7.x 之后新增的配置,节点发现(9300端口慢慢被废弃了)
75 discovery.seed_hosts: ["192.168.124.11:9300", "192.168.124.12:9300", "192.168.124.13:9300"]
// es7.x 之后新增的配置,初始化一个新的集群时,需要此配置来选举 master
79 cluster.initial_master_nodes: ["node-1", "node-2", "node-3"]
88 gateway.recover_after_nodes: 2
89 network.tcp.keep_alive: true
90 network.tcp.no_delay: true
91 transport.tcp.compress: true
// 集群内,同时启动的数据任务个数,默认是2个
94 cluster.routing.allocation.cluster_concurrent_rebalance: 16
// 添加或删除节点,及负载均衡时,并发恢复的线程个数,默认 4个
95 cluster.routing.allocation.node_concurrent_recoveries: 16
// 初始化恢复数据时,并发恢复线程的个数,默认 4 个
96 cluster.routing.allocation.node_initial_primaries_recoveries: 16
-5:修改 vim /etc/security/limits.conf
* -> es
62 * soft nofile 65536
63 * hard nofile 65536
-6:修改: vim /etc/security/limits.d/20-nproc.conf
// 调整最大文件描述
es soft nofile 65536
es hard nofile 65536
* soft nproc 2048
* hard nproc 4096
-7:修改 & 重新加载:vim /etc/sysctl.conf
// 一个进程,在 VMAs(虚拟内存区域),创建内存映射最大数量
vm.max_map_count=655360
vm.swappiness = 1
sysctl -p // 使配置生效
-9: 修改 JVM 启动参数
// 说明:在 Elasticsearch 中,如果 network.host 不是 【localhost 或 127.0.0.1】 的话
// 就会被认为是生产环境,会对环境要求比较高,我们的测试环境不一定能满足,一般需要修改 JVM 启动参数。
-Xms128m // 根据自己机器情况修改
-Xmx128m
4)访问集群测试:GET:http://192.168.124.11:9200/_cat/nodes
192.168.124.13 9 96 45 1.74 1.11 0.59 cdhilmrstw - node-3
192.168.124.12 9 96 11 0.02 0.10 0.18 cdhilmrstw * node-2
192.168.124.11 7 96 9 0.29 0.26 0.25 cdhilmrstw - node-1
5)集群状态查询:GET:192.168.124.11:9200/_cluster/health
{
"cluster_name": "docker-cluster", 集群名称
"status": "yellow", -- 状态(解释如下)--
"timed_out": false, 是否超时
"number_of_nodes": 1, 节点数
"number_of_data_nodes": 1, 数据节点数
"active_primary_shards": 1, 活跃的主要的分片
"active_shards": 1, 活跃度分片
"relocating_shards": 0, 迁移分片
"initializing_shards": 0, 初始化分片
"unassigned_shards": 1, 未签名的分片
"delayed_unassigned_shards": 0, 延迟的未签名的分片
"number_of_pending_tasks": 0, 待定的任务数
"number_of_in_flight_fetch": 0, 航班取来数量
"task_max_waiting_in_queue_millis": 0, 任务在队列中最大等待毫秒数
"active_shards_percent_as_number": 50.0 活跃分片占总数百分比
}
6)访问 ES:GET:http://192.168.124.12:9200/
7)访问 插件:GET:http://192.168.124.12:9200/
8)访问 Kibana:GET:http://192.168.124.12:5601/
4.Linux 集群之 分片和副本
1)介绍:
-1:为了将数据,添加到 Elasticsearch,我们需要 索引(index)【一个存储关联数据的地方】。
-2:实际上,索引只是一个用来指向,一个或多个分片(shards)的 “逻辑命名空间”(logical namespace)。
2)分片:
-1:一个分片(shard):是一个最小级别 “工作单元(worker unit)”,它只是保存了索引中,所有数据的一部分。
-2:我们需要知道:分片就是一个 Lucene 实例。并且它本身,就是一个完整的搜索引擎。应用程序不会和它直接通信。
-3:分片可以是主分片(primary shard),复制分片(副本)(replica shard)。
-4:索引中的每个文档,属于一个单独的主分片,所以主分片的数量,决定了索引最多能存储多少数据。
-5:复制分片,只是主分片的一个副本,它可以防止硬件故障,导致的数据丢失。同时可以提供读请求。(比如:搜索或者从别的 shard 取回文档)
-6:当索引创建完成的时候,主分片的数量就固定了,但是复制分片的数量,可以随时调整。
5.Linux 集群之 故障转移
安装 chrome 插件: Elasticsearch Head。
1)将 1个 data 节点 停止(down机)
结论:对集群没什么影响,会自动修复。
-1:停止之前:
绿色状态:表示所有 10 个分片(5 个主分片、5个副本分片)都在正常运行。
-2:停止之后:
黄色状态:所有主节点可用,副本节点没有全部处于正常状态。
-3:停止一段时间:会自动修复
-4:重启被停止的 data 节点一段时间后:
2)将 master 节点停止(down机)
-1:开始时:
-2:master 停止:重新选举了,master 节点。
-3:master 停止一段时间后:
-4:重启 原 master 节点:(master节点 -> data 节点)
3)脑裂问题:特别说明
6.Linux 集群之 水平扩容
1)如何扩容:
2)
3)如果:我们想要扩容,超过6个节点,怎么办呢?
7.Linux 集群之 分布式文档
1)路由:(计算 存&取 位置)(数据 读&写 流程)
-1:首先看个问题:写数据在集群中,该如何存储?
-2:Elasticsearch 会采用计算的方式,来确定存储位置:
2)文档的写操作:
-1:新建、索引、和删除请求,都是写(write)操作,它们必须在主分片上,成功完成后,才能复制到相关的副本分片上。
-2:执行顺序讲解:
3)搜索文档(读操作)(单个文档)
-1:文档 能够从,主分片 或 任意一个复制分片,被检索。
-2:存在问题:
主分片接到写请求,刚写完主分片数据,未同步到副本分片。
此时新的查询,通过master,计算得到查询位置为副本分片,未能读取到数据,
此现象,为正常现象。
4)全文搜索
-1:对于全文搜索而言,文档可能分散在各个节点上,那么在分布式的情况下,如何搜索文档呢?
搜索分为2个阶段:搜索(query)+取回(fetch)
-2:搜索(query)
-3:取回(fetch)
三.ElasticSearch 入门—初步检索(RestAPI 风格)(105~109):
1._cat:
1)查看所有节点(带 * 为主节点):
GET:http://192.168.124.12:9200/_cat/nodes
172.17.0.2 10 88 36 0.22 0.58 0.74 dilm * d81a418d4cbf
2)查看 es 健康状况:
GET:http://192.168.124.12:9200/_cat/health
1645435075 09:17:55 docker-cluster green 1 1 4 4 0 0 0 0 - 100.0%
3)查看主节点:
GET:http://192.168.124.12:9200/_cat/master
uGYfM7k-SS2gr4ccEUSGTA 172.17.0.2 172.17.0.2 d81a418d4cbf
4)查看所有索引:(show databases)
GET:http://192.168.124.12:9200/_cat/indices?v
health status index uuid pri rep docs.count docs.deleted store.size pri.store.size
green open kibana_sample_data_ecommerce finsdf6wQPCavi8ph21uhQ 1 0 4675 0 4.9mb 4.9mb
green open .kibana_task_manager_1 ePuH1IaiSM6b-F5YSuoG0A 1 0 2 0 38.2kb 38.2kb
green open .apm-agent-configuration l_mb-Xe6RFysKFQoKh5VMw 1 0 0 0 283b 283b
green open .kibana_1 hBDzpOz5SlqwygosaPRdtw 1 0 54 0 933.5kb 933.5kb
2.索引(CRUD)
1)创建非结构化索引:
(对比关系型数据库,创建索引,就等同于创建数据库)
2)因为 PUT 请求是幂等性
(要求每次访问,返回结果都一样),第二次创建相同索引,会报错。
put /customer
// 参数
{
"settings":{
"index":{
"number_of_shards":"2", -- 设置分片数
"number_of_replicas":"0", -- 设置副本数
}
}
}
// 返回值
{
"acknowledged": true, 承认
"shards_acknowledged": true, 碎片_承认
"index": "shopping" 索引
}
2)删除索引:
DELETE:http://192.168.124.12:9200/customer
// 返回值
{
"acknowledged": true
}
3.索引一个文档(保存)
1)保存一个数据,保存在 哪个索引的 哪个类型下,指定用哪一个唯一标识。
(PUT/POST /{索引}/{类型}/{id})(注意请求幂等性要求)
2)customer 索引下,external 类型下,保存1号数据:
-1:元数据(metadata):“_index”,“_type”,“_id” 等
PUT:http://192.168.124.12:9200/customer/external/1
// 数据为:
{
"name":"john"
}
// 返回值为:带 “_”,称作为元数据
{
"_index": "customer", 索引
"_type": "external", 类型(可以是 大写/小写,不能包含“_” 或 “,”)
"_id": "1", id(可手动指定,否则自动生成【32位长度】)
"_version": 1, 版本号(修改一次,版本号叠加)
"result": "created", 请求结果,第二次发送为:update 更新操作
"_shards": { 分片,集群再介绍
"total": 2, 总数
"successful": 1,
"failed": 0
},
"_seq_no": 0,
"_primary_term": 1
}
3)直接保存文档,只使用 索引,不使用类型。
Elasticsearch 7.x 版本中,Type 概念已经被删除了
-1:发送请求:POST 192.168.124.11:9200/shopping/_doc(_doc 可变为 _create)
-2:为什么是 POST ,而不是PUT?:
答:数据创建成功后会返回 _id 属性,随机生成唯一性标识,每次都不一样。不符合幂等性要求。(PUT:幂等性行,不是幂等性也行)
POST 为幂等性请求,每次返回数据都相同,所以不满足。
-3:RESTful & JSON & Postman:
-:安全性:不会改变资源状态,可以理解为只读的;
-:幂等性:执行1次和执行N次,对资源状态改变的效果是等价的。无论对资源操作多少次,结果都是一样的。
4.查询文档:(使用乐观锁)
(避免修改时,并发修改,应携带:?if_seq_no=0&if_primary_term=1 )
(主键查询 和 DSL 查询,如下为主键查询)
GET:http://192.168.124.12:9200/customer/external/1 -- 主键查询
// 返回值:
{
"_index": "customer", 索引
"_type": "external", 类型
"_id": "1", 记录 id
"_version": 18, 版本号(被更新过18次)
"_seq_no": 31, 并发控制字段,用来做乐观所操作(只要数据有改变,值会 +1)
"_primary_term": 1, 并发控制字段,用来做乐观所操作
(主分片发生变化【机器重启/重新选举】,值会 +1)
"found": true, 是否找到数据
"_source": { 数据真实内容
"name": "john"
}
}
5.更新文档(同时可新增属性)(局部更新 & 全量更新):
1)方式一:(局部更新,实际内部操作如下)
-1:从旧文档中,检索JSON
-2:修改它
-3:删除旧文档
-4:索引(插入)新文档
POST:http://192.168.124.12:9200/customer/external/1/_update
// 参数
{
"doc":{
"name":"张三"
}
}
// 返回值:
{
"_index": "customer",
"_type": "external",
"_id": "1",
"_version": 25,
"result": "updated", 操作结果(noop:没有做任何操作)
"_shards": {
"total": 2,
"successful": 1,
"failed": 0
},
"_seq_no": 38,
"_primary_term": 1
}
2)方式二 & 方式三:(做全量的 覆盖修改)
PUT / POST:http://192.168.124.12:9200/customer/external/1
// 参数
{
"name":"李四"
}
// 返回值
{
"_index": "customer",
"_type": "external",
"_id": "1",
"_version": 24,
"result": "updated",
"_shards": {
"total": 2,
"successful": 1,
"failed": 0
},
"_seq_no": 37,
"_primary_term": 1
}
6.删除文档 :
1)说明:删除一个文档,也不会立即从磁盘中移除,他只是被标记为已删除状态。
Elasticsearch 将会在你之后,添加更多索引的时候,才会在后台进行删除内容的清理。
DELETE:http://192.168.124.12:9200/customer/external/1
// 返回值
{
"_index": "customer",
"_type": "external",
"_id": "1",
"_version": 32,
"result": "deleted",
"_shards": {
"total": 2,
"successful": 1,
"failed": 0
},
"_seq_no": 45,
"_primary_term": 1
}
7.bulk 批量 API:
1)打开 Kibana,Dev Tools 界面
2)发送请求:
3)返回数据(每一条都单独返回存储信息,独立统计):
#! Deprecation: [types removal] Specifying types in bulk requests is deprecated.
{
"took" : 4,
"errors" : false,
"items" : [
{
"index" : {
"_index" : "customer2",
"_type" : "external",
"_id" : "1",
"_version" : 2,
"result" : "updated",
"_shards" : {
"total" : 2,
"successful" : 1,
"failed" : 0
},
"_seq_no" : 2,
"_primary_term" : 1,
"status" : 200
}
},
{
"index" : {
"_index" : "customer2",
"_type" : "external",
"_id" : "2",
"_version" : 2,
"result" : "updated",
"_shards" : {
"total" : 2,
"successful" : 1,
"failed" : 0
},
"_seq_no" : 3,
"_primary_term" : 1,
"status" : 200
}
}
]
}
8.样本测试数据(批量导入):
1)数据网址:
https://github.com/elastic/elasticsearch/blob/7.2/docs/src/test/resources/accounts.json?row=true
四.ElasticSearch 进阶检索(SearchAPI & Query DSL)(110~118)
一切方法,参照官方文档:https://www.elastic.co/guide/en/elasticsearch/reference/7.4/index.html
1.SearchAPI:
1)ES 目前支持两种基本检索方式:
-1:使用 REST request URL,发送搜索参数(url + 检索参数)
-2:使用 REST request body,来发送他们(url + 请求体)(也叫:QueryDSL)
https://www.elastic.co/guide/en/elasticsearch/reference/7.4/getting-started-search.html
GET /bank/_search
// 参数
{
"query": {
"match_all": {} 匹配所有
},
"sort": [
{
"account_number": "asc" 按照账号升序排列
}
]
}
// 返回值:
{
"took" : 6, Elasticsearch运行查询所用的时间,以毫秒为单位
"timed_out" : false, 搜索请求是否超时
"_shards" : { 搜索了多少碎片,以及成功、失败或跳过了多少碎片的明细。
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 1000, 全部的值-找到了多少匹配的文档
"relation" : "eq" 检索关系
},
"max_score" : null, 找到的最相关文档的分数
"hits" : [
{
"_index" : "bank",
"_type" : "account",
"_id" : "0",
"_score" : null, 文档的相关性分数(使用match_all时不适用)
"_source" : {
"account_number" : 0,
"balance" : 16623,
"firstname" : "Bradshaw"
.... 数据
},
"sort" : [ 排序-文档的排序位置(不按相关性分数排序时)
0
]
}
]
}
}
2.QueryDSL基本使用 & match等:
1)QueryDSL 介绍:
-1:一个查询语句的典型结构
{
QUERY_NAME:{
ARGUMENT:VALUE,
ARGUMENT:VALUE,....
}
}
-- 如果是针对某个字段,那么结构如下:
{
QUERY_NAME:{
FIELD_NAME:{
ARGUMENT:VALUE,
ARGUMENT:VALUE,....
}
}
}
2)match_all:全部匹配
3)match:限制检索条件
4)from & size :分页:【公式:】
-1:在集群系统中,深度分页:
5)sort:排序
6)_source:想要展示的字段
计算公式:(页码-1)* 每页数据条数
{
"query": {
"match_all": {} 查询全部
},
"sort": [
{
"account_number": "asc" 升序排序
}
],
"_source": ["account_number","balance"], 查询显示的字段
"from": 0, 分页:跳过开始的结果数
"size": 1, 分页:每页显示条数
"_source":{ 想要展示的字段
["title"]
}
}
3.match 匹配查询(自动按 得分进行排序):(单词搜索 / 多词搜索)
1)解释:
-1:match 查询,是一个标准查询,不管你需要全文本查询 / 精确查询,基本上都要用到它。
-2:如果使用 match 查询一个全文本字段,他会在真正查询之前,用分词器,先对要查询的字段进行分词后查询。
-3:如果:match 下指定了一个确切值,【在遇到 数字、日期、布尔值、not_analyzed 的 字符串】时,它将为你准确匹配搜索你给定的值。
2)匹配查询:基本类型(非字符串),精确匹配:
GET /bank/_search. (结果得分1.0)
{
"query": {
"match": {
"balance": "16623"
}
}
}
3)匹配查询:字符串,模糊匹配查询(全文检索):
4)使用 ik 分词器后,多词搜索:多个词语,都需要匹配。
【可选择:“and” 和 “or” 的关系】(比较极端)。
5)实际应用中,更多使用下面用法:
(设置匹配度)(通过实际中反复测试,确定合理的值)
【and:100%;or:0%】
4.match_phrase 短语匹配(自动按 得分进行排序):
1)解释:将 需要匹配的词,当成一个整体单词(不分词)进行搜索。
2)使用:
GET /bank/_search
{
"query": {
"match_phrase": {
"address": "Madison Street"
}
}
}
5.multi_match 多字段匹配(自动按 得分进行排序):
1)解释:匹配其中任意一个即可被查询出。
2)使用:
GET /bank/_search
{
"query": {
"multi_match": {
"query": "mill Brogan", 可以进行分词。
"fields": ["city","address"] 其中一个,有(mill / Brogan)即可被查询出
}
}
}
6.bool 复合查询 :
1)bool 解释:查询可以用来合并多个条件查询结果的布尔逻辑,它包含以下操作符:
-1:must:多个查询条件的完全匹配,相当于 and。
-2:must_mot:多个查询条件的反匹配,相当于not。
-3:should:如果匹配上,则得分更高,更优先显示。(可手动指定权重,会影响得分,详解在后面)
注意:如果查询语句中,没有 must,那么至少要有一个查询条件匹配,should 则相当于 or。(也可以通过 minmun_should_match 百分比参数进行控制)
-4:这些参数,可以分别继承一个查询条件,或者一个查询条件的数组 [ ]。
1)解释:复合语句,可以合并 任何其它查询语句,包括复合语句。
这就意味着,复合语句,可以互相嵌套,可以表达非常复杂的逻辑。
2)使用:
GET /bank/_search
{
"query": {
"bool": {
"must": [ 必须满足,数组
{
"match": {
"gender": "f"
}
},
{
"match": {
"address": "Lane"
}
}
],
"must_not": [ 必须不满足
{
"match": {
"balance": "38172"
}
}
],
"should": [ 满足其中任一条件即可
{
"match": {
"address": "Lane"
}
}
]
}
}
}
7.filter 过滤 & range 范围查询 & exists 存在查询:
1)filter 解释:并不是所有的查询,都需要产生分数,特别是那些仅用于 “filtering”(过滤)的文档。
为了【不计算分数】,Elasticsearch 会自动检查场景,并且优化查询的执行。
(过滤条件结果:无分数)
-1:查询和过滤对比:
2)range 解释:range 过滤,允许我们按照指定范围,查找一批数据。
-1:gt:大于
-2:gte:大于等于
-3:lt:小于(LT)
-4:lte:小于等于
3)使用:
GET /bank/_search
{
"query": {
"bool": {
"must": [
{
"range": { 查询范围
"age": { 年龄 大于等于10 并且 小于等于20
"gte": 10,
"lte": 20
}
}
}
]
}
}
}
4)exists 查询:
-1:exists 查询:可以用于查找文档中是否包含指定字段,类似于 SQL 语句中的 IS_NULL 条件。
8.term 查询:
1)解释:和 match 一样,匹配某个属性的值。文档全文检索字段用 match;其他非 text 字段匹配用 term。
(用于检索某些准确的值(用于精确匹配某些值)【例如:数字、日期、布尔值、price、id等】)。
2)官网解释:https://www.elastic.co/guide/en/elasticsearch/reference/8.0/query-dsl-term-query.html
3)请求事例:
4)terms:批量匹配
9.权重:(在 bool 的 should 下使用)
1)解释:有些时候,我们可能需要,对某些词语,增加权重,来影响该条数据的得分,从而达到优先显示的目的。
2)使用:
10.highlight 高亮显示:
{
"query": {
"match_phrase": {
"category": "小"
}
},
"highlight":{ 高亮查询显示(写法固定)
"fields":{
"category":{
}
}
}
}
11.aggregations 聚合分析(分析功能):
1)解释:
-1:聚合,提供了从数据中分组和提取数据的能力。最简单的聚合方法,大致等于 SQL:GROUP BY 和 SQL 聚合函数。
-2:在 Elasticsearch 中,您有执行搜索返回 hits(命中结果),并且同时返回聚合结果,把一个响应中的所有hits(命中结果)分割开的能力。
-3:可以执行查询和多个聚合,并且在一次使用中,得到各自的(任何一个的)返回结果,使用一次简洁和简化的 API,来避免网络往返。
-4:事例
{
"aggs": { // 聚合操作
"price_group": { //名称,随意起名
"terms": { //分组
"field": "price" //分组字段
}
}
},
"size": 0
}
{
"aggs": { // 聚合操作
"price_avg": { //名称,随意起名
"avg": { //平均值
"field": "price" //计算平均值字段
}
}
},
"size": 0
}
2)使用(1):搜索 address 中包含 mill 的所有人的年龄分布,以及平均年龄,但不显示这些人的详情。
3)使用(2):按照年龄聚合,并且请求这些年龄段的这些人的平均薪资
4)使用(3):查出所有年龄分布,并且这些年龄段中 M 的平均薪资 和 F的平均薪资,以及这个年龄段的总体平均薪资。(gender.leyword:精确匹配)
12.评分的计算规则:
五.ElasticSearch 映射(119~121)
1.:创建映射
1):字段类型(几乎涵盖了所有类型,详见官网)
2):映射(Mapping)
-1:前面我们创建的索引,以及插入数据,都是由 Elasticsearch 进行自动判断类型,但是有些时候,我们是需要进行,明确字段类型的,否则,自动判断的类型,和实际的需求是不相符的。
-2:自动判断类型规则如下:
-2:Elasticsearch 中,支持的类型如下:
-3:Mapping 是用来定义一个文档(document),以及它所包含的属性(field),是如何存储和索引的。
3):使用 Mapping 定义:
-1:新增 mapping 信息(例如下面 2种方式)
{
"properties": {
"name": {
"type": "text", 文本,可以分词
"index": "true" 可以索引查询
},
"sex": {
"type": "keyword", 不能够分词,必须完全匹配
"index": true 可以索引查询
}
}
}
-2:查看 mapping 信息:(/my_index/_mapping)
2.:添加新的字段映射(需指定索引)
3.:更新映射:对于,已经存在的映射字段,是不能更新的,更新必须创建新的索引,进行数据迁移。
4.:数据迁移
1)查询要被修改的索引:
2)复制老索引,修改,后创建新的索引:
3)用如下方法,进行数据迁移:新迁移的数据,不会使用 type(已被取消)
六.ElasticSearch — ik分词(Analysis)(122~124)
1.:分词器 解释:
1)什么是分词:就是指,讲一个文本,转化为一系列单词的过程,也叫文本分析。在 Elasticsearch 中,称之为 Analysis。
2.:安装 ik 分词器
1)测试默认分词器如何分词:会将单词中的汉字,一个个提取出来,粗暴的分词。
GET _analyze
{
"analyzer": "standard", 使用标准(默认)分词器
"text": "第一"
}
2)IK Analyzer 介绍:
详见:git-readme:https://github.com/medcl/elasticsearch-analysis-ik/blob/master/README.md
3)安装 ik 分词器:
-1:docker 安装
// 注意:</font>不能用默认 elasticsearch-plugin install xxx.zip 进行自动安装。
// 下载网址:(同7.4.2版本)</font>https://github.com/medcl/elasticsearch-analysis-ik/releases?page=5
进入容器:docker exec -it d81a418d4cbf /bin/bash
安装插件:./bin/elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.4.2/elasticsearch-analysis-ik-7.4.2.zip
-2:文件安装(ik版本一定要和 es版本一致,才可启动)
// https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.11.1/elasticsearch-analysis-ik-7.11.1.zip
// 1、将 下载的 elasticsearch-analysis-ik-6.5.4.zip,
// 解压到 /elasticsearch/plugins/ik 目录下即可。
mkdir /es/plugins/ik
unzip elasticsearch-analysis-ik-6.5.4.zip
// 重启 es
kill 进程号
./bin/elasticsearch
4)测试分词效果:
在结果中,不仅可以看出分词结果,还返回了该词,在文本中的位置信息。
3.:自定义拓展词库
1)修改 ik 分词器的配置文件(XML):
4.:通过 ik 分词器检索
1)
2)
3)
七.ElasticSearch 整合 SpringBoot
1.:整合 high-level-client
1)Elasticsearch 提供了 2种 REST 客户端。(9200 HTTP)(9300将被废弃)
-1:Java Low Level REST client:
-2:Java High Level REST client:
Elasticsearch-Rest-Client:官方 RestClient,封装了 ES 操作,提供了很多便捷的API,API 层次分明,上手简单。
官网:https://www.elastic.co/guide/en/elasticsearch/client/java-rest/current/index.html
2)整合开始(高版本):
-1:引入 依赖(和 ES 版本相同),并修改 SpingBoot 自带版本
<?xml version="1.0" encoding="UTF-8"?>
<properties>
<java.version>1.8</java.version>
<elasticsearch.version>7.4.2</elasticsearch.version>
</properties>
<dependencies>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>7.4.2</version>
</dependency>
</dependencies>
</project>
-2:编写配置类
/**
* @author zhangxudong@chunyu.me
* @date 2022/2/22 5:34 下午
*/
@Configuration
public class ElasticSearchConfig {
/**
* 给容器中,注入 RestHighLevelClient
*/
@Bean
public RestHighLevelClient restHighLevelClient() {
HttpHost http1 = new HttpHost("192.168.124.11", 9200, "http");
HttpHost http2 = new HttpHost("192.168.124.12", 9200, "http");
HttpHost http3 = new HttpHost("192.168.124.13", 9200, "http");
RestClientBuilder builder = RestClient.builder(http1, http2, http3);
RestHighLevelClient client = new RestHighLevelClient(builder);
return client;
}
}
-3:使用
@Autowired
private RestHighLevelClient restHighLevelClient;
2.:保存测试
@RequestMapping(value = "addIndex")
public String addIndex() throws IOException {
IndexRequest indexRequest = new IndexRequest("users").id("123");
// 方式 1
// indexRequest.source("username", "zhangsan", "age", 18, "gender", "男");
// 方式2
User user = new User("张三", 20);
String jsonString = JSON.toJSONString(user);
indexRequest.source(jsonString, XContentType.JSON);
// 索引保存
IndexResponse index = restHighLevelClient.index(indexRequest, RequestOptions.DEFAULT);
return "成功";
}
3.:测试复杂检索
1)简单查询:
@RequestMapping(value = "/search")
public String search() throws IOException {
// 1:创建检索请求
SearchRequest searchRequest = new SearchRequest();
// 1.1:指定索引
searchRequest.indices("bank");
// 1.2:指定DSL,检索条件(求:不同年龄的平均薪资)
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
sourceBuilder.query(QueryBuilders.matchAllQuery())
.aggregation(AggregationBuilders.terms("age_terms").field("age").size(10)
.subAggregation(AggregationBuilders.avg("balance_avg").field("balance")));
System.out.println(sourceBuilder.toString());//打印检索条件
searchRequest.source(sourceBuilder);
// 2:获取检索信息
SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
System.out.println(searchResponse.toString());//打印查询结果
return "成功";
}
2)结果分析:
-1:转为map
-2:使用 自带的 get 方法
-3:封装为对象
3):
4):
5):
6):