一.ElasticSearch简介
1、ElasticSearch(简称ES)
Elasticsearch是用Java开发并且是当前最流行的开源的企业级搜索引擎。
能够达到近实时搜索,稳定,可靠,快速,安装使用方便。
客户端支持Java、.NET(
C#)、PHP、Python、Ruby等多种语言。
官方网站: https://www.elastic.co/
下载地址: https://www.elastic.co/cn/start
创始人: Shay Banon(谢巴农)
2、应用场景 3、ElasticSearch与Lucene的关系 Lucene可以被认为是迄今为止最先进、性能最好的、功能最全的搜索引擎库(框
架)
但是想要使用Lucene,必须使用Java来作为开发语言并将其直接集成到你的应用
中,并且Lucene的配置及使用非常复杂,你需要深入了解检索的相关知识来理解
它是如何工作的。
Lucene缺点:
1)只能在Java项目中使用,并且要以jar包的方式直接集成项目中.
2)使用非常复杂-创建索引和搜索索引代码繁杂
3)不支持集群环境-索引数据不同步(不支持大型项目)
4)索引数据如果太多就不行,索引库和应用所在同一个服务器,共同占用硬
盘.共用空间少.
上述Lucene框架中的缺点,ES全部都能解决.
4、哪些公司在使用Elasticsearch
1 1. 京东
2 2. 携程
3 3. 去哪儿
4 4. 58 同城
5 5. 滴滴
6 6. 今日头条
7 7. 小米
8 8. 哔哩哔哩
9 9. 联想
10 10. GitHup
11 11. 微软
12 12. Facebook
13 等等 ...
5、ES vs Solr比较
5.1、ES vs Solr 检索速度 当单纯的对已有数据进行搜索时,Solr更快。
当实时建立索引时, Solr会产生io阻塞,查询性能较差, Elasticsearch具有明
显的优势。
大型互联网公司,实际生产环境测试,将搜索引擎从Solr转到 Elasticsearch以
后的平均查询速度有了50倍的提升。
总结:
二者安装都很简单。 1、Solr 利用 Zookeeper 进行分布式管理,而Elasticsearch 自身带有分布式
协调管理功能。
2、Solr 支持更多格式的数据,比如JSON、XML、CSV,而 Elasticsearch 仅支
持json文件格式。
3、Solr 在传统的搜索应用中表现好于 Elasticsearch,但在处理实时搜索应用
时效率明显低于 Elasticsearch。
4、Solr 是传统搜索应用的有力解决方案,但 Elasticsearch更适用于新兴的实
时搜索应用。
5.2、ES vs 关系型数据库
二、Lucene全文检索框架
1、什么是全文检索
全文检索是指:
通过一个程序扫描文本中的每一个单词,针对单词建立索引,并保存
该单词在文本中的位置、以及出现的次数
用户查询时,通过之前建立好的索引来查询,将索引中单词对应的文
本位置、出现的次数返回给用户,因为有了具体文本的位置,所以就可以
将具体内容读取出来了 hello elasticSearch ==》
hello
elasticSearch
"index":true,"store":true
2、分词原理之倒排索引
倒排索引总结:
索引就类似于目录,平时我们使用的都是索引,都是通过主键定位到某条数据,
那么倒排索引呢,刚好相反,数据对应到主键.这里以一个博客文章的内容为
例:
1.索引
文章ID
文章标题
文章内容
1
浅析JAVA设计模式
JAVA设计模式是每一个JAVA程序
员都应该掌握的进阶知识
2
JAVA多线程设计模式
JAVA多线程与设计模式结合
2.倒排索引 假如,我们有一个站内搜索的功能,通过某个关键词来搜索相关的文章,那么这
个关键词可能出现在标题中,也可能出现在文章内容中,那我们将会在创建或修
改文章的时候,建立一个关键词与文章的对应关系表,这种,我们可以称之为倒
排索引,因此倒排索引,也可称之为反向索引.如:
关键词
文章ID
JAVA
1
设计模式
1,2
多线程
2
注:这里涉及中文分词的问题
三、Elasticsearch中的核心概念
1、索引 index
一个索引就是一个拥有几分相似特征的文档的集合。比如说,可以有一个客户
数据的索引,另一个产品目录的索引,还有一个订单数据的索引
一个索引由一个名字来标识(必须全部是小写字母的),并且当我们要对对应
于这个索引中的文档进行索引、搜索、更新和删除的时候,都要使用到这个名字
2、映射 mapping
ElasticSearch中的映射(
Mapping)用来定义一个文档
mapping是处理数据的方式和规则方面做一些限制,如某
个字段的数据类型、默认值、分词器、是否被索引等等,
这些都是映射里面可以设置的
3、字段Field
相当于是数据表的字段|列 4、字段类型 Type
每一个字段都应该有一个对应的类型,例如:Text、Keyword、Byte等
5、文档 document
一个文档是一个可被索引的基础信息单元,类似一条记录。文档以JSON(
Javascript
Object Notation)格式来表示;
6、集群 cluster
一个集群就是由一个或多个节点组织在一起,它们共同持有整个的数据,并一起
提供索引和搜索功能
7、节点 node
一个节点是集群中的一个服务器,作为集群的一部分,它存储数据,参与集群的
索引和搜索功能
一个节点可以通过配置集群名称的方式来加入一个指定的集群。默认情况下,每
个节点都会被安排加入到一个叫做“
elasticsearch”的集群中
这意味着,如果在网络中启动了若干个节点,并假定它们能够相互发现彼此,它
们将会自动地形成并加入到一个叫做“
elasticsearch”的集群中
在一个集群里,可以拥有任意多个节点。而且,如果当前网络中没有运行任何
Elasticsearch节点,这时启动一个节点,会默认创建并加入一个叫
做“
elasticsearch”的集群。
8、分片和副本 shards&replicas
8.1、分片
一个索引可以存储超出单个结点硬件限制的大量数据。比如,一个具
有10亿文档的索引占据1TB的磁盘空间,而任一节点都没有这样大的磁盘空
间;或者单个节点处理搜索请求,响应太慢 为了解决这个问题,Elasticsearch提供了将索引划分成多份的能力,
这些份就叫做分片
当创建一个索引的时候,可以指定你想要的分片的数量
每个分片本身也是一个功能完善并且独立的“索引”,这个“索
引”可以被放置到集群中的任何节点上
分片很重要,主要有两方面的原因
允许水平分割/扩展你的内容容量
允许在分片之上进行分布式的、并行的操作,进而提高性能/吞吐量
至于一个分片怎样分布,它的文档怎样聚合回搜索请求,是完全由
Elasticsearch管理的,对于作为用户来说,这些都是透明的
8.2、副本
在一个网络/云的环境里,失败随时都可能发生,在某个分片/节点不
知怎么的就处于离线状态,或者由于任何原因消失了,这种情况下,有一
个故障转移机制是非常有用并且是强烈推荐的。为此目的,Elasticsearch
允许你创建分片的一份或多份拷贝,这些拷贝叫做副本分片,或者直接叫
副本
副本之所以重要,有两个主要原因
1) 在分片/节点失败的情况下,提供了高可用性。
注意到复制分片从不与原/主要(
original/primary)分片
置于同一节点上是非常重要的
2) 扩展搜索量/吞吐量,因为搜索可以在所有的副本上并行运行
每个索引可以被分成多个分片。一个索引有0个或者多个副
一旦设置了副本,每个索引就有了主分片和副本分片,分片
和副本的数量可以在索引 创建的时候指定
在索引创建之后,可以在任何时候动态地改变副本的数量,但
是不能改变分片的数量
四、安装Elasticsearch
1、安装Elasticsearch
1.1、创建普通用户
ES不能使用root用户来启动,必须使用普通用户来安装启动 。这里我们创建一
个普通用户以及定义一些常规目录用于存放我们的数据文件以及安装包等。
创建一个es专门的用户( 必须
# 使用root用户在服务器执行以下命令
1 先创建组 , 再创建用户 :
2 1 )创建 elasticsearch 用户组
3 [ root@localhost ~ ] # groupadd elasticsearch
4
5 2 )创建用户 tlbaiqi 并设置密码
6 [ root@localhost ~ ] # useradd tlbaiqi
7 [ root@localhost ~ ] # passwd tlbaiqi
8
9 3 # 创建 es 文件夹,
10 并修改 owner baiqi 用户
11 mkdir p / usr / local / es
12
13 4 )用户 es 添加到 elasticsearch 用户组
14 [ root@localhost ~ ] # usermod G elasticsearch tlbaiqi
15 [ root@localhost ~ ] # chown R tlbaiqi / usr / local / es / elasticsearch 7.6.1
16
17 5 )设置 sudo 权限
18 # 为了让普通用户有更大的操作权限,我们一般都会给普通用户设置 sudo 权限,方便普通用
户的操作
19 # 三台机器使用 root 用户执行 visudo 命令然后为 es 用户添加权限
20 [ root@localhost ~ ] # visudo
21
22 # root ALL = ( ALL ) ALL 一行下面
23 # 添加 tlbaiqi 用户 如下 :
24 tlbaiqi ALL = ( ALL ) ALL 25
26 # 添加成功保存后切换到 tlbaiqi 用户操作
27
28 [ root@localhost ~ ] # su tlbaiqi
29 [ tlbaiqi@localhost root ] $
30
1.2、上传压缩包并解压
将es的安装包下载并上传到服务器的/user/local/es路径下,然后进行解压
使用tlbaiqi用户来执行以下操作,将es安装包上传到指定服务器,并使用es用
户执行以下命令解压。
1 # 解压 Elasticsearch
2 su tlbaiqi
3 cd / user / local /
4 tar zvxf elasticsearch 7.6.1 linux x86_64 . tar . gz C / usr / local / es /
1.3、修改配置文件
1.3.1、修改elasticsearch.yml
进入服务器使用 baiqi 用户 来修改配置文件
1
2 mkdir p / usr / local / es / elasticsearch 7.6.1 / log
3 mkdir p / usr / local / es / elasticsearch 7.6.1 / data
4
5
6 cd / usr / local / es / elasticsearch 7.6.1 / config
7 vim elasticsearch . yml
8 cluster . name : my application
9 node . name : node 1
10 path . data : / usr / local / es / elasticsearch 7.6.1 / data
11 path . logs : / usr / local / es / elasticsearch 7.6.1 / log
12 network . host : 0.0.0.0
13 http . port : 9200
14 discovery . seed_hosts : [ " 服务器 IP" ]
15 cluster . initial_master_nodes : [ "node‐1" ]
16 bootstrap . system_call_filter : false
17 bootstrap . memory_lock : false
18 http . cors . enabled : true 19 http . cors . allow origin : "*"
1.3.2、修改jvm.option
修改jvm.option配置文件,调整jvm堆内存大小
node1.baiqi.cn使用baiqi用户 执行以下命令调整jvm堆内存大小,每个人根据
自己服务器的内存大小来进行调整。
1 cd / usr / local / es / elasticsearch 7.6.1 / config
2 vi jvm . options
3 Xms2g
4 Xmx2g
2、修改系统配置,解决启动时候的问题
由于现在使用普通用户来安装es服务,且es服务对服务器的资源要求比较多,包
括内存大小,线程数等。所以我们需要给普通用户解开资源的束缚
2.1、普通用户打开文件的最大数限制
问题错误信息描述:
max file descriptors [4096] for elasticsearch process likely too low,
increase to at least [65536]
ES因为需要大量的创建索引文件,需要大量的打开系统的文件,所以我们需要解
除linux系统当中打开文件最大数目的限制,不然ES启动就会抛错
三台机器使用baiqi用户执行以下命令解除打开文件数据的限制
sudo vi /etc/security/limits.conf
添加如下内容: 注意*不要去掉了
1 * soft nofile 65536
2 * hard nofile 131072
3 * soft nproc 4096
4 * hard nproc 4096
此文件修改后需要重新登录用户,才会生效
2.2、普通用户启动线程数限制 问题错误信息描述
max number of threads [1024] for user [es] likely too low, increase to
at least [4096]
修改普通用户可以创建的最大线程数
max number of threads [1024] for user [es] likely too low, increase to
at least [4096] 原因:无法创建本地线程问题,用户最大可创建线程数太小解决
方案:修改90-nproc.conf 配置文件。
三台机器使用baiqi用户执行以下命令修改配置文件
1 Centos6
2 sudo vi / etc / security / limits . d / 90 nproc . conf
3 Centos7
4 sudo vi / etc / security / limits . d / 20 nproc . conf
找到如下内容:
1 * soft nproc 1024 # 修改为
2 * soft nproc 4096
2.3、普通用户调大虚拟内存
错误信息描述:
max virtual memory areas vm.max_map_count [65530] likely too low,
increase to at least [262144]
调大系统的虚拟内存
原因:最大虚拟内存太小
每次启动机器都手动执行下。
三台机器执行以下命令
1 vi / etc / sysctl . conf ,追加以下内容: vm . max_map_count = 655360 保存后,执行: sys
ctl p
备注:以上三个问题解决完成之后,重新连接secureCRT或者重新连接xshell生效
3、启动ES服务
三台机器使用baiqi用户执行以下命令启动es服务
cd /usr/local/es/elasticsearch-7.6.1/bin/ 后台启动ES
./elasticsearch -d
启动成功之后jsp即可看到es的服务进程,并且访问页面
http:// 192.168.21.128 :9200/?pretty
能够看到es启动之后的一些信息
注意:如果哪一台机器服务启动失败,那么就到哪一台机器的
/usr/local/es/elasticsearch-7.6.1/log
这个路径下面去查看错误日志
1 关闭 Linux 防火墙
2 永久性生效,重启后不会复原
3 开启: chkconfig iptables on
4 关闭: chkconfig iptables off
5 即时生效,重启后复原
6 开启: service iptables start
7 关闭: service iptables stop
8 centos7 关闭防火墙 systemctl stop firewalld . service
注意:启动ES的时候出现 Permission denied
原因:当前的用户没有对XX文件或目录的操作权限
五、客户端Kibana安装
1、客户端可以分为图形界面客户端,和代码客户端.
2、ES主流客户端Kibana,开放9200端口与图形界面客户端交互
1)下载Kibana放之/usr/local/es目录中
2)解压文件:tar -zxvf kibana-X.X.X-linux-x86_64.tar.gz
3)进入/usr/local/es/kibana-X.X.X-linux-x86_64/config目录
4)使用vi编辑器:vi kibana.yml
1 server . port : 5601
2 server . host : " 服务器 IP"
3 elasticsearch . hosts : [ "http://IP:9200" ] # 这里是 elasticsearch 的访问地址
5)启动Kibana 启动kibana
1 cd / usr / local / es / kibana 7.6.1 linux x86_64 / bin
./ kibana
后台启动kibana
1 nohup . / kibana &
6)访问Kibana
http://ip:5601/app/kibana
六、安装IK分词器
我们后续也需要使用Elasticsearch来进行中文分词,所以需要单独给
Elasticsearch安装IK分词器插件。以下为具体安装步骤:
1、下载Elasticsearch IK分词器
https://github.com/medcl/elasticsearch-analysis-ik/releases
2、切换到baiqi用户,并在es的安装目录下/plugins创建ik
1 mkdir p / usr / local / es / elasticsearch 7.6.1 / plugins / ik
3、将下载的ik分词器上传并解压到该目录
1 cd / usr / local / es / elasticsearch 7.6.1 / plugins / ik
2 解压 elasticsearch analysis ik 7.6.1 . zip
4、重启Elasticsearch
5、测试分词效果
1 POST _analyze
2 {
3 "analyzer" : "standard" ,
4 "text" : " 我爱你中国 "
5 }
1 POST _analyze
2 { 3 "analyzer" : "ik_smart" ,
4 "text" : " 中华人民共和国 "
5 }
6 #ik_smart : 会做最粗粒度的拆分
1 POST _analyze
2 {
3 "analyzer" : "ik_max_word" ,
4 "text" : " 中华人民共和国 "
5 }
6 #ik_max_word : 会将文本做最细粒度的拆分
七、指定IK分词器作为默认分词器
ES的默认分词设置是standard,这个在中文分词时就比较尴尬了,会单字拆分,
比如我搜索关键词“清华大学”,这时候会
按“清”,“华”,“大”,“学”去分词,然后搜出来的都是些“清清的河
水”,“中华儿女”,“地大物博”,“学而不思则罔”之类的莫名其妙的结
果,这里我们就想把这个分词方式修改一下,于是呢,就想到了ik分词器,有两
种ik_smart和ik_max_word。
ik_smart会将“清华大学”整个分为一个词,而ik_max_word会将“清华大
学”分为“清华大学”,“清华”和“大学”,按需选其中之一就可以了。
修改默认分词方法(这里修改school_index索引的默认分词为:ik_max_word):
1 PUT / school_index
2 {
3 "settings" : {
4 "index" : {
5 "analysis.analyzer.default.type" : "ik_max_word"
6 }
7 }
8 }
八、ES数据管理
1、ES数据管理概述 ES是面向文档(document oriented)的 ,这意味着它可以存储整个对象或文档
(document)。
然而它不仅仅是存储,还会索引(index)每个文档的内容使之可以被搜索。
在ES中,你可以对文档(而非成行成列的数据)进行索引、搜索、排序、过滤。
ES使用 JSON 作为文档序列化格式。
JSON现在已经被大多语言所支持,而且已经成为NoSQL领域的标准格式。
ES存储的一个员工文档的格式示例:
1 {
2 "email" : "584614151@qq.com" ,
3 "name" : " 张三 " ,
4 "age" : 30 ,
5 "interests" : [ " 篮球 " , " 健身 " ]
6
7 }
2、基本操作
1) 创建索引
格式: PUT /索引名称
1 举例 : PUT / es_db
2) 查询索引
格式: GET /索引名称
1 举例 : GET / es_db
3) 删除索引
格式: DELETE /索引名称
1 举例 : DELETE / es_db
4) 添加文档
格式: PUT /索引名称/类型/id
1 举例 :
2 PUT / es_db / _doc / 1
3 {
4 "name" : " 张三 " , 5 "sex" : 1 ,
6 "age" : 25 ,
7 "address" : " 广州天河公园 "
8 }
9
10 PUT / es_db / _doc / 2
11 {
12 "name" : " 李四 " ,
13 "sex" : 1 ,
14 "age" : 28 ,
15 "address" : " 广州荔湾大厦 "
16 }
17
18 PUT / es_db / _doc / 3
19 {
20 "name" : " 王五 " ,
21 "sex" : 0 ,
22 "age" : 26 ,
23 "address" : " 广州白云山公园 "
24 }
25
26 PUT / es_db / _doc / 4
27 {
28 "name" : "admin" ,
29 "sex" : 0 ,
30 "age" : 22 ,
31 "address" : " 长沙橘子洲头 "
32 }
33
34 PUT / es_db / _doc / 5
35 {
36 "name" : " 小明 " ,
37 "sex" : 0 ,
38 "age" : 19 ,
39 "address" : " 长沙岳麓山 "
40 }
5) 修改文档
1 格式 : PUT / 索引名称 / 类型 / id
2 举例 : 3 PUT / es_db / _doc / 1
4 {
5 "name" : " 白起老师 " ,
6 "sex" : 1 ,
7 "age" : 25 ,
8 "address" : " 张家界森林公园 "
9 }
6) 查询文档
1 格式 : GET / 索引名称 / 类型 / id
2 举例 : GET / es_db / _doc / 1
7) 删除文档
1 格式 : DELETE / 索引名称 / 类型 / id
2 举例 : DELETE / es_db / _doc / 1
九、查询操作
1、查询当前类型中的所有文档 _search
1 格式 : GET / 索引名称 / 类型 / _search
2 举例 : GET / es_db / _doc / _search
3 SQL : select * from student
2、条件查询, 如要查询age等于28岁的 _search?q=*:***
1 格式 : GET / 索引名称 / 类型 / _search ? q =* : ***
2 举例 : GET / es_db / _doc / _search ? q = age : 28
3 SQL : select * from student where age = 28
3、范围查询, 如要查询age在25至26岁之间的 _search?q=***[** TO **] 注
意: TO 必须为大写
1 格式 : GET / 索引名称 / 类型 / _search ? q =*** [ 25 TO 26 ]
2 举例 : GET / es_db / _doc / _search ? q = age [ 25 TO 26 ]
3 SQL : select * from student where age between 25 and 26
4、根据多个ID进行批量查询 _mget
1 格式 : GET / 索引名称 / 类型 / _mget
2 举例 : GET / es_db / _doc / _mget 3 {
4 "ids" :[ "1" , "2" ]
5 }
6 SQL : select * from student where id in ( 1 , 2 )
5、查询年龄小于等于28岁的 :<=
1 格式 : GET / 索引名称 / 类型 / _search ? q = age : <=**
2 举例 : GET / es_db / _doc / _search ? q = age : <= 28
3 SQL : select * from student where age <= 28
6、查询年龄大于28前的 :>
1 格式 : GET / 索引名称 / 类型 / _search ? q = age : >**
2 举例 : GET / es_db / _doc / _search ? q = age : > 28
3 SQL : select * from student where age > 28
7、分页查询 from=*&size=*
1 格式 : GET / 索引名称 / 类型 / _search ? q = age [ 25 TO 26 ] & from = 0 & size = 1
2 举例 : GET / es_db / _doc / _search ? q = age [ 25 TO 26 ] & from = 0 & size = 1
3 SQL : select * from student where age between 25 and 26 limit 0 , 1
8、对查询结果只输出某些字段 _source=字段,字段
1 格式 : GET / 索引名称 / 类型 / _search ? _source = 字段 , 字段
2 举例 : GET / es_db / _doc / _search ? _source = name , age
3 SQL : select name , age from student
9、对查询结果排序 sort=字段:desc/asc
1 格式 : GET / 索引名称 / 类型 / _search ? sort = 字段 desc
2 举例 : GET / es_db / _doc / _search ? sort = age : desc
3 SQL : select * from student order by age desc
十、DSL语言高级查询
ES提供了强大的查询语言(
DSL),它可以允许我们进行更加强大、复杂的查
询,Elasticsearch DSL中有Query与Filter两种 1、Query方式查询,会在ES中索引的数据都会存储一个_score分值,分值越高就
代表越匹配。另外关于某个搜索的分值计算还是很复杂的,因此也需要一定的时
间。
根据名称精确查询姓名 term, term查询不会对字段进行分词查询,会
采用精确匹配
注意: 采用term精确查询, 查询字段映射类型属于为keyword.
举例:
1 POST / es_db / _doc / _search
2 {
3 "query" : {
4 "term" : {
5 "name" : "admin"
6 }
7 }
8 }
1 SQL : select * from student where name = 'admin'
根据备注信息模糊查询 match, match会根据该字段的分词器,进行分
词查询
举例:
1 POST / es_db / _doc / _search
2 {
3 "from" : 0 ,
4 "size" : 2 ,
5 "query" : {
6 "match" : {
7 "address" : " 广州 "
8 }
9 }
10 }
1 SQL : select * from user where address like '% 广州 %' limit 0 , 2 多字段模糊匹配查询与精准查询 multi_match
1 POST / es_db / _doc / _search
2 {
3 "query" :{
4 "multi_match" :{
5 "query" : " 张三 " ,
6 "fields" :[ "address" , "name" ]
7 }
8 }
9 }
1 SQL : select * from student where name like '% 张三 %' or address like '%
%'
范围查询
注:json请求字符串中部分字段的含义
range:范围关键字
gte 大于等于
lte 小于等于
gt 大于
lt 小于
now 当前时间
1 POST / es_db / _doc / _search
2 {
3 "query" : {
4 "range" : {
5 "age" : {
6 "gte" : 25 ,
7 "lte" : 28
8 }
9 }
10 }
11 } 1 SQL : select * from user where age between 25 and 28
分页、输出字段、排序综合查询
1 POST / es_db / _doc / _search
2 {
3 "query" : {
4 "range" : {
5 "age" : {
6 "gte" : 25 ,
7 "lte" : 28
8 }
9 }
10 },
11 "from" : 0 ,
12 "size" : 2 ,
13 "_source" : [ "name" , "age" , "book" ],
14 "sort" : { "age" : "desc" }
15 }
2、Filter过滤器方式查询,它的查询不会计算相关性分值,也不会对结果进
行排序, 因此效率会高一点,查询的结果可以被缓存。
Filter Context 对数据进行过滤
1 POST / es_db / _doc / _search
2 {
3 "query" : {
4 "bool" : {
5 "filter" : {
6 "term" :{
7 "age" : 25
8 }
9 }
10 }
11 }
12 }
十一、文档映射 1、ES中映射可以分为动态映射和静态映射
动态映射:
在关系数据库中,需要事先创建数据库,然后在该数据库下创建数据表,并创建
表字段、类型、长度、主键等,最后才能基于表插入数据。而Elasticsearch中
不需要定义Mapping映射(即关系型数据库的表、字段等),在文档写入
Elasticsearch时,会根据文档字段自动识别类型,这种机制称之为动态映射。
动态映射规则如下:
静态映射:
静态映射是在Elasticsearch中也可以事先定义好映射,包含文档的各字段类
型、分词器等,这种方式称之为静态映射。
2、动态映射
2.1、删除原创建的索引
1 DELETE / es_db
2.2、创建索引
1 PUT / es_db
2.3、创建文档(ES根据数据类型, 会自动创建映射)
1 PUT / es_db / _doc / 1
2 {
3 "name" : "Jack" ,
4 "sex" : 1 ,
5 "age" : 25 , 6 "book" : "java 入门至精通 " ,
7 "address" : " 广州小蛮腰 "
8 }
2.4、获取文档映射
1 GET / es_db / _mapping
3、静态映射
3.1、删除原创建的索引
1 DELETE / es_db
3.2、创建索引
1 PUT / es_db
3.3、设置文档映射
1 PUT / es_db
2 {
3 "mappings" :{
4 "properties" :{
5 "name" :{ "type" : "keyword" , "index" : true , "store" : true },
6 "sex" :{ "type" : "integer" , "index" : true , "store" : true },
7 "age" :{ "type" : "integer" , "index" : true , "store" : true },
8 "book" :{ "type" : "text" , "index" : true , "store" : true },
9 "address" :{ "type" : "text" , "index" : true , "store" : true }
10 }
11 }
12 }
3.4、根据静态映射创建文档
1 PUT / es_db / _doc / 1
2 {
3 "name" : "Jack" ,
4 "sex" : 1 ,
5 "age" : 25 ,
6 "book" : "elasticSearch 入门至精通 " , 7 "address" : " 广州车陂 "
8 }
3.5、获取文档映射
1 GET / es_db / _mapping
十二、keyword 与 text 映射类型的区别
将 book 字段设置为 keyword 映射 (只能精准查询, 不能分词查询,能聚合、
排序)
1 POST / es_db / _doc / _search
2 {
3 "query" : {
4 "term" : {
5 "book" : "elasticSearch 入门至精通 "
6 }
7 }
8 }
将 book 字段设置为 text 映射
(能模糊查询, 能分词查询,不能聚合、排
序)
1 POST / es_db / _doc / _search
2 {
3 "query" : {
4 "match" : {
5 "book" : "elasticSearch 入门至精通 "
6 }
7 }
8 }
十三、创建静态映射时指定text类型的ik分词器
1、设置ik分词器的文档映射
先删除之前的es_db
再创建新的es_db 定义ik_smart的映射
1 PUT / es_db
2 {
3 "mappings" :{
4 "properties" :{
5 "name" :{ "type" : "keyword" , "index" : true , "store" : true },
6 "sex" :{ "type" : "integer" , "index" : true , "store" : true },
7 "age" :{ "type" : "integer" , "index" : true , "store" : true },
8 "book" :{ "type" : "text" , "index" : true , "store" : true ,
9 "analyzer" : "ik_smart" ,
10 "search_analyzer" : "ik_smart" },
11 "address" :{ "type" : "text" , "index" : true , "store" : true }
12 }
13 }
14 }
* 分词查询
1 POST / es_db / _doc / _search
2 {
3 "query" : {
4 "match" : {
5 "address" : " 广 "
6 }
7 }
8 }
9
10 POST / es_db / _doc / _search
11 {
12 "query" : {
13 "match" : {
14 "address" : " 广州 "
15 }
16 }
17 }
18
十四、ES集群环境搭建 1、修改elasticsearch.yml
node1.baiqi.cn 服务器使用 baiqi 用户 来修改配置文件
1 cd / usr / local / es / elasticsearch 7.6.1 / config
2 mkdir p / usr / local / es / elasticsearch 7.6.1 / log
3 mkdir p / usr / local / es / elasticsearch 7.6.1 / data
4 rm rf elasticsearch . yml
5
6 vim elasticsearch . yml
7 cluster . name : baiqi es
8 node . name : node1 . baiqi . cn
9 path . data : / usr / local / es / elasticsearch 7.6.1 / data
10 path . logs : / usr / local / es / elasticsearch 7.6.1 / log
11 network . host : node1 . baiqi . cn
12 http . port : 9200
13 discovery . seed_hosts : [ "IP1" , "IP2" , "IP3" ]
14 cluster . initial_master_nodes : [ " 节点 1 名称 " , " 节点 2 名称 " , " 节点 3 名称 " ]
15 bootstrap . system_call_filter : false
16 bootstrap . memory_lock : false
17 http . cors . enabled : true
18 http . cors . allow origin : "*"
2 、修改jvm.option
修改jvm.option配置文件,调整jvm堆内存大小
node1.baiqi.cn使用baiqi用户 执行以下命令调整jvm堆内存大小,每个人根据
自己服务器的内存大小来进行调整。
1 cd / usr / local / es / elasticsearch 7.6.1 / config
2 vim jvm . options
3 Xms2g
4 Xmx2g
3、将安装包分发到其他服务器上面
4、node2与node3修改es配置文件
node2.baiqi.cn与node3.baiqi.cn也需要修改es配置文件
node2.baiqi.cn使用baiqi用户执行以下命令修改es配置文件 1 cd / usr / local / es / elasticsearch 7.6.1 / config
2 mkdir p / usr / local / es / elasticsearch 7.6.1 / log
3 mkdir p / usr / local / es / elasticsearch 7.6.1 / data
4
5 vim elasticsearch . yml
6 cluster . name : baiqi es
7 node . name : node2 . baiqi . cn
8 path . data : / usr / local / es / elasticsearch 7.6.1 / data
9 path . logs : / usr / local / es / elasticsearch 7.6.1 / log
10 network . host : node2 . baiqi . cn
11 http . port : 9200
12 discovery . seed_hosts : [ "IP1" , "IP2" , "IP3" ]
13 cluster . initial_master_nodes : [ " 节点 1 名称 " , " 节点 2 名称 " , " 节点 3 名称 " ]
14 bootstrap . system_call_filter : false
15 bootstrap . memory_lock : false
16 http . cors . enabled : true
17 http . cors . allow origin : "*"
node3.baiqi.cn使用baiqi用户执行以下命令修改配置文件
1 cd / usr / local / es / elasticsearch 7.6.1 / config
2 mkdir p / usr / local / es / elasticsearch 7.6.1 / log
3 mkdir p / usr / local / es / elasticsearch 7.6.1 / data
4
5 vim elasticsearch . yml
6 cluster . name : baiqi es
7 node . name : node3 . baiqi . cn
8 path . data : / usr / local / es / elasticsearch 7.6.1 / data
9 path . logs : / usr / local / es / elasticsearch 7.6.1 / log
10 network . host : node3 . baiqi . cn
11 http . port : 9200
12 discovery . seed_hosts : [ "IP1" , "IP2" , "IP3" ]
13 cluster . initial_master_nodes : [ " 节点 1 名称 " , " 节点 2 名称 " , " 节点 3 名称 " ]
14 bootstrap . system_call_filter : false
15 bootstrap . memory_lock : false
16 http . cors . enabled : true
17 http . cors . allow origin : "*" 十五、Elasticsearch-head 插件
由于es服务启动之后,访问界面比较丑陋,为了更好的查看索引库当中的信息,
我们可以通过安装elasticsearch-head这个插件来实现,这个插件可以更方便快
捷的看到es的管理界面
elasticsearch-head这个插件是es提供的一个用于图形化界面查看的一个插件工
具,可以安装上这个插件之后,通过这个插件来实现我们通过浏览器查看es当中
的数据
安装elasticsearch-head这个插件这里提供两种方式进行安装,第一种方式就是
自己下载源码包进行编译,耗时比较长,网络较差的情况下,基本上不可能安装
成功。
第二种方式就是直接使用我已经编译好的安装包,进行修改配置即可
要安装elasticsearch-head插件,需要先安装Node.js
1、安装nodejs
Node.js是一个基于 Chrome V8 引擎的 JavaScript 运行环境。
Node.js是一个Javascript运行环境(runtime environment),发布于2009年5
月,由Ryan Dahl开发,实质是对Chrome V8引擎进行了封装。Node.js 不是一个
JavaScript 框架,不同于CakePHP、Django、Rails。Node.js 更不是浏览器端
的库,不能与 jQuery、ExtJS 相提并论。Node.js 是一个让 JavaScript 运行
在服务端的开发平台,它让 JavaScript 成为与PHP、Python、Perl、Ruby 等服
务端语言平起平坐的脚本语言。
1.1、下载安装包
node1.baiqi.cn机器执行以下命令下载安装包,然后进行解压
1 cd / usr / local / es
2 wget https : // npm . taobao . org / mirrors / node / v8 . 1.0 / node v8 . 1.0 linux
x64 . tar . gz
3 tar zxvf node v8 . 1.0 linux x64 . tar . gz C / usr / local / es /
1.2、创建软连接
node1.baiqi.cn执行以下命令创建软连接 1 sudo ln s / usr / local / es / node v8 . 1.0 linux x64 / lib / node_modules / npm / bin / n
pm cli . js / usr / local / bin / npm
2 sudo ln s / usr / local / es / node v8 . 1.0 linux x64 / bin / node / usr / local / bin / no
de
1.3、修改环境变量
node1.baiqi.cn服务器添加环境变量
1 vi / etc / profile
2 export NODE_HOME =/ usr / local / es / node v8 . 1.0 linux x64
3 export PATH = : $ PATH : $ NODE_HOME / bin
修改完环境变量使用source生效
1 source / etc / profile
1.4、验证安装成功
node1.baiqi.cn执行以下命令验证安装生效
1 node v
2 npm v
2、 本地安装
2 .1、上传压缩包到/usr/local/es路径下去
将我们的压缩包 elasticsearch-head-compile-after.tar.gz 上传到服务器
的/usr/local/es 路径下面去
2 .2、解压安装包
在服务器中执行以下命令解压安装包
1 cd / usr / local / es /
2 tar zxvf elasticsearch head compile after . tar . gz C / usr / local / es /
2.3、 node1.baiqi.cn 机器修改Gruntfile.js
修改Gruntfile.js这个文件
1 cd / usr / local / es / elasticsearch head
2 vim Gruntfile . js 找到代码中的93行:hostname: '192.168.100.100', 修改为:node1.baiqi.cn
1 connect : {
2 server : {
3 options : {
4 hostname : 'node1.baiqi.cn' ,
5 port : 9100 ,
6 base : '.' ,
7 keepalive : true
8 }
9 }
10 }
2.4、 node1机器修改app.js
第一台机器修改app.js
1 cd / usr / local / es / elasticsearch head / _site
2 vim app . js
1 Vim 中输入「 : 4354 」,定位到第 4354 行,修改 http : // localhost : 9200 http : // nod
e1 . baiqi . cn : 9200
2.5、 启动head服务
node1.baiqi.cn启动elasticsearch-head插件
1 cd / usr / local / es / elasticsearch head / node_modules / grunt / bin /
进程前台启动命令
1 . / grunt server
进程后台启动命令
1 nohup . / grunt server >/ dev / null 2 >& 1 &
1 Running "connect:server" ( connect ) taskWaiting forever ... Started connect
web server on http : // 192.168.52.100 : 9100
2 如何停止: elasticsearch head 进程
3 执行以下命令找到 elasticsearch head 的插件进程,然后使用 kill 9 杀死进程即可
4 netstat nltp | grep 9100 5 kill 9 8328
2.6、访问elasticsearch-head界面
打开Google Chrome访问
http://ip:9100/
注意:搭建es集群,启动三个es节点,访问elasticsearch-head时只显示一个
master
解决方案:进到节点2、3的/elasticsearch-7.6.1/data/目录下删除nodes文
件,之后重启节点2、3的es进程即可
十六、Java API操作ES
1)配置Maven依赖
1 < dependencies >
2 <!‐‐ ES 的高阶的客户端 API ‐‐>
3 < dependency >
4 < groupId > org . elasticsearch . client </ groupId >
5 < artifactId > elasticsearch rest high level client </ artifactId >
6 < version > 7.6.1 </ version >
7 </ dependency >
8 < dependency >
9 < groupId > org . apache . logging . log4j </ groupId >
10 < artifactId > log4j core </ artifactId >
11 < version > 2.11.1 </ version >
12 </ dependency >
13 <!‐‐ 阿里巴巴出品的一款将 Java 对象转换为 JSON 、将 JSON 转换为 Java 对象的库 ‐‐>
14 < dependency >
15 < groupId > com . alibaba </ groupId >
16 < artifactId > fastjson </ artifactId >
17 < version > 1.2.62 </ version > 18 </ dependency >
19 < dependency >
20 < groupId > junit </ groupId >
21 < artifactId > junit </ artifactId >
22 < version > 4.12 </ version >
23 < scope > test </ scope >
24 </ dependency >
25 < dependency >
26 < groupId > org . testng </ groupId >
27 < artifactId > testng </ artifactId >
28 < version > 6.14.3 </ version >
29 < scope > test </ scope >
30 </ dependency >
31
32 </ dependencies >
2)代码较多参照实际工程
十七、Elasticsearch重要工作流程
1、Elasticsearch文档写入原理
1.选择任意一个DataNode发送请求,例如:node2。此时,node2就成为一个
coordinating node(协调节点)
2.计算得到文档要写入的分片 `shard = hash(routing) % number_of_primary_shards`
routing 是一个可变值,默认是文档的 _id
3.coordinating node会进行路由,将请求转发给对应的primary shard所在的
DataNode(假设primary shard在node1、replica shard在node2)
4.node1节点上的Primary Shard处理请求,写入数据到索引库中,并将数据同步
到Replica shard
5.Primary Shard和Replica Shard都保存好了文档,返回client
2、Elasticsearch检索原理
client发起查询请求,某个DataNode接收到请求,该DataNode就会成为协调节
点(
Coordinating Node)
协调节点(
Coordinating Node)将查询请求广播到每一个数据节点,这些数据
节点的分片会处理该查询请求
每个分片进行数据查询,将符合条件的数据放在一个优先队列中,并将这些数
据的文档ID、节点信息、分片信息返回给协调节点
协调节点将所有的结果进行汇总,并进行全局排序
协调节点向包含这些文档ID的分片发送get请求,对应的分片将文档数据返回给
协调节点,最后协调节点将数据返回给客户端
十八、Elasticsearch准实时索引实现 1、溢写到文件系统缓存
当数据写入到ES分片时,会首先写入到内存中,然后通过内存的buffer生成一个
segment,并刷到 文件系统缓存 中,数据可以被检索(注意不是直接刷到磁盘)
ES中默认1秒,refresh一次
2、写translog保障容错
在写入到内存中的同时,也会记录translog日志,在refresh期间出现异常,会
根据translog来进行数据恢复
等到文件系统缓存中的segment数据都刷到磁盘中,清空translog文件
3、flush到磁盘
ES默认每隔30分钟会将文件系统缓存的数据刷入到磁盘
4、segment合并
Segment太多时,ES定期会将多个segment合并成为大的segment,减少索引查询
时IO开销,此阶段ES会真正的物理删除(之前执行过的delete的数据) 十九、ElasticSearch文档分值_score计算 底层原理
1)boolean model
根据用户的query条件,先过滤出包含指定term的doc
1 query "hello world" ‐‐> hello / world / hello & world
2
3 bool ‐‐> must / must not / should ‐‐> 过滤 ‐‐> 包含 / 不包含 / 可能包含
4
5 doc ‐‐> 不打分数 ‐‐> 正或反 true or false ‐‐> 为了减少后续要计算 doc 的数量,
提升性能
2)relevance score算法,简单来说,就是计算出,一个索引中的文本,与搜索
文本,他们之间的关联匹配程度
Elasticsearch使用的是 term frequency/inverse document frequency算法,
简称为TF/IDF算法
Term frequency :搜索文本中的各个词条在field文本中出现了多少次,出现次
数越多,就越相关
1 搜索请求: hello world
2
3
4
5 doc1 hello you , and world is very good
6
7 doc2 hello , how are you
8
Inverse document frequency :搜索文本中的各个词条在整个索引的所有文档
中出现了多少次,出现的次数越多,就越不相关 1 搜索请求: hello world
2
3
4
5 doc1 hello , tuling is very good
6
7 doc2 hi world , how are you
8
比如说,在index中有1万条document,hello这个单词在所有的document中,一
共出现了1000次;world这个单词在所有的document中,一共出现了100次
Field-length norm:field长度,field越长,相关度越弱
搜索请求:hello world
1 doc1 { "title" : "hello article" , "content" : "...... N 个单词 " }
2
3 doc2 { "title" : "my article" , "content" : "...... N 个单词, hi world" }
4
hello world在整个index中出现的次数是一样多的
doc1更相关,title field更短
2、分析一个document上的_score是如何被计算出来的
1 GET / es_db / _doc / 1 / _explain
2 {
3 "query" : {
4 "match" : {
5 "remark" : "java developer"
6 } 7 }
8 }
二十、es生产集群部署之针对生产集群的脑裂问题专门定制的重要参数
集群脑裂是什么?
所谓脑裂问题,就是同一个集群中的不同节点,对于集群的状态有了不一样
的理解,比如集群中存在两个master
如果因为网络的故障,导致一个集群被划分成了两片,每片都有多个node,
以及一个master,那么集群中就出现了两个master了。
但是因为master是集群中非常重要的一个角色,主宰了集群状态的维护,以
及shard的分配,因此如果有两个master,可能会导致数据异常。
如:
节点1在启动时被选举为主节点并保存主分片标记为0P,而节点2保存复制分
片标记为0R
现在,如果在两个节点之间的通讯中断了,会发生什么?由于网络问题或只
是因为其中一个节点无响应,这是有可能发生的。
两个节点都相信对方已经挂了。节点1不需要做什么,因为它本来就被选举为主
节点。但是节点2会自动选举它自己为主节点,因为它相信集群的一部分没有主 节点了。
在elasticsearch集群,是有主节点来决定将分片平均的分布到节点上的。节点2
保存的是复制分片,但它相信主节点不可用了。所以它会自动提升Node2节点为
主节点。
现在我们的集群在一个不一致的状态了。打在节点1上的索引请求会将索引数据
分配在主节点,同时打在节点2的请求会将索引数据放在分片上。在这种情况
下,分片的两份数据分开了,如果不做一个全量的重索引很难对它们进行重排
序。在更坏的情况下,一个对集群无感知的索引客户端(例如,使用REST接口
的),这个问题非常透明难以发现,无论哪个节点被命中索引请求仍然在每次都
会成功完成。问题只有在搜索数据时才会被隐约发现:取决于搜索请求命中了哪
个节点,结果都会不同。
那么那个参数的作用,就是告诉es直到有足够的master候选节点时,才可以选举
出一个master,否则就不要选举出一个master。这个参数必须被设置为集群中
master候选节点的quorum数量,也就是大多数。至于quorum的算法,就是:
master候选节点数量 / 2 + 1。
比如我们有10个节点,都能维护数据,也可以是master候选节点,那么quorum就
是10 / 2 + 1 = 6。
如果我们有三个master候选节点,还有100个数据节点,那么quorum就是3 / 2 +
1 = 2 如果我们有2个节点,都可以是master候选节点,那么quorum是2 / 2 + 1 = 2。
此时就有问题了,因为如果一个node挂掉了,那么剩下一个master候选节点,是
无法满足quorum数量的,也就无法选举出新的master,集群就彻底挂掉了。此时
就只能将这个参数设置为1,但是这就无法阻止脑裂的发生了。
2个节点,discovery.zen.minimum_master_nodes分别设置成2和1会怎么样
综上所述,一个生产环境的es集群,至少要有3个节点,同时将这个参数设置为
quorum,也就是2。discovery.zen.minimum_master_nodes设置为2,如何避免脑
裂呢?
那么这个是参数是如何避免脑裂问题的产生的呢?比如我们有3个节点,quorum
是2.现在网络故障,1个节点在一个网络区域,另外2个节点在另外一个网络
域,不同的网络区域内无法通信。这个时候有两种情况情况:
1)如果master是单独的那个节点,另外2个节点是master候选节点,那么此时
那个单独的master节点因为没有指定数量的候选master node在自己当前所在的
集群内,因此就会取消当前master的角色,尝试重新选举,但是无法选举成功。
然后另外一个网络区域内的node因为无法连接到master,就会发起重新选举,因
为有两个master候选节点,满足了quorum,因此可以成功选举出一个master。此
时集群中就会还是只有一个master。
2)如果master和另外一个node在一个网络区域内,然后一个node单独在一个
网络区域内。那么此时那个单独的node因为连接不上master,会尝试发起选举,
但是因为master候选节点数量不到quorum,因此无法选举出master。而另外一个
网络区域内,原先的那个master还会继续工作。这也可以保证集群内只有一个
master节点。
综上所述,集群中master节点的数量至少3台,三台主节点通过在
elasticsearch.yml中配置discovery.zen.minimum_master_nodes: 2,就可以避 免脑裂问题的产生。
Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐