ElasticSearch
Posted java_wxid
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ElasticSearch相关的知识,希望对你有一定的参考价值。
文章目录
- 1.ElasticSearch简介
- 2. Lucene全文检索框架
- 3. Elasticsearch中的核心概念
- 4. 安装Elasticsearch
- 5 客户端Kibana安装
- 6 安装IK分词器
- 7、指定IK分词器作为默认分词器
- 8.ES数据管理
- 9.Restful认识
- 10.查询操作
- 11.文档批量操作
- 12.DSL语言高级查询
- 13.文档映射
- 14.核心类型(Core datatype)
- 15.keyword 与 text 映射类型的区别
- 16.创建静态映射时指定text类型的ik分词器
- 17.对已存在的mapping映射进行修改
- 18.Elasticsearch乐观并发控制
- 19.Java API操作ES
- 20.ES集群环境搭建
- 21.Elasticsearch-head插件
- 22.Elasticsearch架构原理
- 23.分片和副本机制
- 24.Elasticsearch重要工作流程
- 25.Elasticsearch准实时索引实现
- 26.手工控制搜索结果精准度
- 27.经验分享
- 28.前缀搜索 prefix search
- 29.通配符搜索
- 30.正则搜索
- 31.搜索推荐
- 32.fuzzy模糊搜索技术
1.ElasticSearch简介
1.1 ElasticSearch(简称ES)
Elasticsearch是用Java开发并且是当前最流行的开源的企业级搜索引擎。能够达到实时搜索,稳定,可靠,快速,安装使用方便。客户端支持Java、.NET(C#)、php、Python、Ruby等多种语言。
官方网站: https://www.elastic.co/
下载地址:https://www.elastic.co/cn/start
1.2 ElasticSearch与Lucene的关系
Lucene可以被认为是迄今为止最先进、性能最好的、功能最全的搜索引擎库(框架)但是想要使用Lucene,必须使用Java来作为开发语言并将其直接集成到你的应用中,并且Lucene的配置及使用非常复杂,你需要深入了解检索的相关知识来理解它是如何工作的。
Lucene缺点:
1)只能在Java项目中使用,并且要以jar包的方式直接集成项目中.
2)使用非常复杂-创建索引和搜索索引代码繁杂
3)不支持集群环境-索引数据不同步(不支持大型项目)
4)索引数据如果太多就不行,索引库和应用所在同一个服务器,共同占用硬盘.共用空间少.
上述Lucene框架中的缺点,ES全部都能解决.
1.3 哪些公司在使用Elasticsearch
- 京东
- 携程
- 去哪儿
- 58同城
- 滴滴
- 今日头条
- 小米
- 哔哩哔哩
- 联想
- GitHup
- 微软
等等…
1.4 ES vs Solr比较
1.4.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更适用于新兴的实时搜索应用。
1.4.2 ES vs 关系型数据库
2. Lucene全文检索框架
2.1 什么是全文检索
通过一个程序扫描文本中的每一个单词,针对单词建立索引,并保存该单词在文本中的位置、以及出现的次数。用户查询时,通过之前建立好的索引来查询,将索引中单词对应的文本位置、出现的次数返回给用户,因为有了具体文本的位置,所以就可以将具体内容读取出来了。
2.2 分词原理之倒排索引
倒排索引总结:
索引就类似于目录,平时我们使用的都是索引,都是通过主键定位到某条数据,那么倒排索引呢,刚好相反,数据对应到主键。
以一个博客文章的内容为例:
1.索引
2.倒排索引
假如,我们有一个站内搜索的功能,通过某个关键词来搜索相关的文章,那么这个关键词可能出现在标题中,也可能出现在文章内容中,那我们将会在创建或修改文章的时候,建立一个关键词与文章的对应关系表,这种,我们可以称之为倒排索引,因此倒排索引,也可称之为反向索引。
3. Elasticsearch中的核心概念
3.1 索引 index
一个索引就是一个拥有几分相似特征的文档的集合。比如说,可以有一个客户数据的索引,另一个产品目录的索引,还有一个订单数据的索引。
一个索引由一个名字来标识(必须全部是小写字母的),并且当我们要对对应于这个索引中的文档进行索引、搜索、更新和删除的时候,都要使用到这个名字。
3.2 映射 mapping
ElasticSearch中的映射(Mapping)用来定义一个文档。mapping是处理数据的方式和规则方面做一些限制,如某个字段的数据类型、默认值、分词器、是否被索引等等,这些都是映射里面可以设置的
3.3 字段Field
相当于是数据表的字段|列
3.4 字段类型 Type
每一个字段都应该有一个对应的类型,例如:Text、Keyword、Byte等
3.5 文档 document
一个文档是一个可被索引的基础信息单元,类似一条记录。文档以JSON(javascript Object Notation)格式来表示;
3.6 集群 cluster
一个集群就是由一个或多个节点组织在一起,它们共同持有整个的数据,并一起提供索引和搜索功能
3.7 节点 node
一个节点是集群中的一个服务器,作为集群的一部分,它存储数据,参与集群的索引和搜索功能。
一个节点可以通过配置集群名称的方式来加入一个指定的集群。默认情况下,每个节点都会被安排加入到一个“elasticsearch”的集群中。在一个集群里,可以拥有任意多个节点。而且,如果当前网络中没有运行任何Elasticsearch节点,这时启动一个节点,会默认创建并加入一个叫做“elasticsearch”的集群。
3.8 分片和副本 shards&replicas
3.8.1 分片
一个索引可以存储超出单个结点硬件限制的大量数据。比如,一个具有10亿文档的索引占据1TB的磁盘空间,而任一节点都没有这样大的磁盘空间;或者单个节点处理搜索请求,响应太慢。
为了解决这个问题,Elasticsearch提供了将索引划分成多份的能力,这些份就叫做分片。
当创建一个索引的时候,可以指定你想要的分片的数量,每个分片本身也是一个功能完善并且独立的“索引”,这个“索引”可以被放置到集群中的任何节点上,分片很重要,主要有两方面的原因:允许水平分割/扩展你的内容容量允许在分片之上进行分布式的、并行的操作,进而提高性能/吞吐量。至于一个分片怎样分布,它的文档怎样聚合回搜索请求,是完全由Elasticsearch管理的,对于作为用户来说,这些都是透明的
3.8.2 副本
在一个网络/云的环境里,失败随时都可能发生,在某个分片/节点不知怎么的就处于离线状态,或者由于任何原因消失了,这种情况下,有一个故障转移机制是非常有用并且是强烈推荐的。为此目的,Elasticsearch允许你创建分片的一份或多份拷贝,这些拷贝叫做副本分片,或者直接叫副本。
副本之所以重要,有两个主要原因
- 在分片/节点失败的情况下,提供了高可用性。注意到复制分片从不与原/主要(original/primary)分片置于同一节点上是非常重要的。
- 扩展搜索量/吞吐量,因为搜索可以在所有的副本上并行运行。每个索引可以被分成多个分片。一个索引有0个或者多个副本
一旦设置了副本,每个索引就有了主分片和副本分片,分片和副本的数量可以在索引。创建的时候指定,在索引创建之后,可以在任何时候动态地改变副本的数量,但是不能改变分片的数量。
4. 安装Elasticsearch
4.1 安装Elasticsearch
4.1.1 创建普通用户
ES不能使用root用户来启动,必须使用普通用户来安装启动。这里我们创建一个普通用户以及定义一些常规目录用于存放我们的数据文件以及安装包等。
创建一个es专门的用户(必须)
使用root用户在服务器执行以下命令
先创建组, 再创建用户:
1)创建 elasticsearch 用户组
[root@localhost ~]# groupadd elasticsearch
2)创建用户 tlbaiqi 并设置密码
[root@localhost ~]# useradd tlbaiqi
[root@localhost ~]# passwd tlbaiqi
3)# 创建es文件夹,
并修改owner为baiqi用户
mkdir -p /usr/local/es
4)用户es 添加到 elasticsearch 用户组
[root@localhost ~]# usermod -G elasticsearch tlbaiqi
[root@localhost ~]# chown -R tlbaiqi /usr/local/es/elasticsearch-7.6.1
5)设置sudo权限
#为了让普通用户有更大的操作权限,我们一般都会给普通用户设置sudo权限,方便普通用户的操作
#三台机器使用root用户执行visudo命令然后为es用户添加权限
[root@localhost ~]# visudo
#在root ALL=(ALL) ALL 一行下面
#添加tlbaiqi用户 如下:
tlbaiqi ALL=(ALL) ALL
#添加成功保存后切换到tlbaiqi用户操作
[root@localhost ~]# su tlbaiqi
[tlbaiqi@localhost root]$
4.1.2 上传压缩包并解压
将es的安装包下载并上传到服务器的/user/local/es路径下,然后进行解压
使用tlbaiqi用户来执行以下操作,将es安装包上传到指定服务器,并使用es用户执行以下命令解压。
# 解压Elasticsearch
su tlbaiqi
cd /user/local/
tar -zvxf elasticsearch-7.6.1-linux-x86_64.tar.gz -C /usr/local/es/
4.1.3 修改配置文件
4.1.3.1 修改elasticsearch.yml
进入服务器使用baiqi用户来修改配置文件
cd /usr/local/es/elasticsearch-7.6.1/config
mkdir -p /usr/local/es/elasticsearch-7.6.1/log
mkdir -p /usr/local/es/elasticsearch-7.6.1/data
rm -rf elasticsearch.yml
vim elasticsearch.yml
cluster.name: baiqi-es
node.name: node1
path.data: /usr/local/es/elasticsearch-7.6.1/data
path.logs: /usr/local/es/elasticsearch-7.6.1/log
network.host: 0.0.0.0
http.port: 9200
discovery.seed_hosts: ["服务器IP"]
cluster.initial_master_nodes: ["节点名"]
bootstrap.system_call_filter: false
bootstrap.memory_lock: false
http.cors.enabled: true
http.cors.allow-origin: "*"
4.1.3.2 修改jvm.option
修改jvm.option配置文件,调整jvm堆内存大小。
node1.baiqi.cn使用baiqi用户执行以下命令调整jvm堆内存大小,每个人根据自己服务器的内存大小来进行调整。
cd /usr/local/es/elasticsearch-7.6.1/config
vim jvm.options
-Xms2g
-Xmx2g
4.2 修改系统配置,解决启动时候的问题
由于现在使用普通用户来安装es服务,且es服务对服务器的资源要求比较多,包括内存大小,线程数等。所以我们需要给普通用户解开资源的束缚。
4.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
添加如下内容: 注意*不要去掉了
* soft nofile 65536
* hard nofile 131072
* soft nproc 2048
* hard nproc 4096
4.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用户执行以下命令修改配置文件
Centos6
sudo vi /etc/security/limits.d/90-nproc.conf
Centos7
sudo vi /etc/security/limits.d/20-nproc.conf
找到如下内容:
* soft nproc 1024#修改为
* soft nproc 4096
4.2.3 普通用户调大虚拟内存
错误信息描述:
max virtual memory areas vm.max_map_count [65530] likely too low, increase to at least [262144]
原因:最大虚拟内存太小,解决方案:调大系统的虚拟内存,每次启动机器都手动执行下。三台机器执行以下命令
编辑 /etc/sysctl.conf,追加以下内容:vm.max_map_count=262144 保存后,执行:sysctl -p
备注:以上三个问题解决完成之后,重新连接secureCRT或者重新连接xshell生效
4.3 启动ES服务
三台机器使用baiqi用户执行以下命令启动es服务
nohup /usr/local/es/elasticsearch-7.6.1/bin/elasticsearch 2>&1 &
后台启动ES 进入bin目录 ./elasticsearch -d
启动成功之后jsp即可看到es的服务进程,并且访问页面
http://ip:9200/?pretty
能够看到es启动之后的一些信息
注意:如果哪一台机器服务启动失败,那么就到哪一台机器的
/usr/local/es/elasticsearch-7.6.1/log
这个路径下面去查看错误日志
关闭Linux防火墙
永久性生效,重启后不会复原
开启: chkconfig iptables on
关闭: chkconfig iptables off
即时生效,重启后复原
开启: service iptables start
关闭: service iptables stop
注意:启动ES的时候出现 Permission denied。原因:当前的用户没有对XX文件或目录的操作权限。
5 客户端Kibana安装
5.1客户端可以分为图形界面客户端,和代码客户端.
5.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
server.port: 5601
server.host: "服务器IP"
elasticsearch.hosts: ["http://IP:9200"] #这里是elasticsearch的访问地址
5)启动Kibana
/usr/local/es/kibana-7.6.1-linux-x86_64/bin/kibana
后台启动kibana
nohup ./kibana &
6)访问Kibana
http://ip:5601/app/kibana
6 安装IK分词器
我们后续也需要使用Elasticsearch来进行中文分词,所以需要单独给Elasticsearch安装IK分词器插件。以下为具体安装步骤:
6.1 下载Elasticsearch IK分词器
https://github.com/medcl/elasticsearch-analysis-ik/releases
6.2 切换到baiqi用户,并在es的安装目录下/plugins创建ik
mkdir -p /usr/local/es/elasticsearch-7.6.1/plugins/ik
6.3 将下载的ik分词器上传并解压到该目录
cd /usr/local/es/elasticsearch-7.6.1/plugins/ik
unzip elasticsearch-analysis-ik-7.6.1.zip
6.4 重启Elasticsearch
6.5 测试分词效果
POST _analyze
"analyzer":"standard",
"text":"我爱你中国"
POST _analyze
"analyzer": "ik_smart",
"text": "中华人民共和国"
#ik_smart:会做最粗粒度的拆分
POST _analyze
"analyzer":"ik_max_word",
"text":"我爱你中国"
#ik_max_word:会将文本做最细粒度的拆分
7、指定IK分词器作为默认分词器
ES的默认分词设置是standard,这个在中文分词时就比较尴尬了,会单字拆分,比如我搜索关键词“清华大学”,这时候会按“清”,“华”,“大”,“学”去分词,然后搜出来的都是些“清清的河水”,“中华儿女”,“地大物博”,“学而不思则罔”之类的莫名其妙的结果,这里我们就想把这个分词方式修改一下,于是呢,就想到了ik分词器,有两种ik_smart和ik_max_word。ik_smart会将“清华大学”整个分为一个词,而ik_max_word会将“清华大学”分为“清华大学”,“清华”和“大学”,按需选其中之一就可以了。修改默认分词方法(这里修改school_index索引的默认分词为:ik_max_word):
PUT /school_index
"settings" :
"index" :
"analysis.analyzer.default.type": "ik_max_word"
8.ES数据管理
8.1 ES数据管理概述
ES是面向文档(document oriented)的,这意味着它可以存储整个对象或文档(document)。然而它不仅仅是存储,还会索引(index)每个文档的内容使之可以被搜索。在ES中,你可以对文档(而非成行成列的数据)进行索引、搜索、排序、过滤。
ES使用JSON作为文档序列化格式。JSON现在已经被大多语言所支持,而且已经成为NoSQL领域的标准格式。
ES存储的一个员工文档的格式示例:
"email": "584614151@qq.com",
"name": "张三",
"age": 30,
"interests": [ "篮球", "健身" ]
8.2 基本操作
1) 创建索引
格式: PUT /索引名称
举例: PUT /es_db
2) 查询索引
格式: GET /索引名称
举例: GET /es_db
3) 删除索引
格式: DELETE /索引名称
举例: DELETE /es_db
4) 添加文档
格式: PUT /索引名称/类型/id
举例:
PUT /es_db/_doc/1
"name": "张三",
"sex": 1,
"age": 25,
"address": "广州天河公园",
"remark": "java developer"
PUT /es_db/_doc/2
"name": "李四",
"sex": 1,
"age": 28,
"address": "广州荔湾大厦",
"remark": "java assistant"
PUT /es_db/_doc/3
"name": "rod",
"sex": 0,
"age": 26,
"address": "广州白云山公园",
"remark": "php developer"
PUT /es_db/_doc/4
"name": "admin",
"sex": 0,
"age": 22,
"address": "长沙橘子洲头",
"remark": "python assistant"
PUT /es_db/_doc/5
"name": "小明",
"sex": 0,
"age": 19,
"address": "长沙岳麓山",
"remark": "java architect assistant"
5) 修改文档
格式: PUT /索引名称/类型/id
举例:
PUT /es_db/_doc/1
"name": "白起老师",
"sex": 1,
"age": 25,
"address": "张家界森林公园",
"remark": "php developer assistant"
注意:POST和PUT都能起到创建/更新的作用
1、需要注意的是PUT需要对一个具体的资源进行操作也就是要确定id才能进行更新/创建,而POST是可以针对整个资源集合进行操作的,如果不写id就由ES生成一个唯一id进行创建==新文档,如果填了id那就针对这个id的文档进行创建/更新
2、PUT只会将json数据都进行替换,POST只会更新相同字段的值。
3、PUT与DELETE都是幂等性操作,即不论操作多少次, 结果都一样。
6) 查询文档
格式: GET /索引名称/类型/id
举例: GET /es_db/_doc/1
7) 删除文档
格式: DELETE /索引名称/类型/id
举例: DELETE /es_db/_doc/1
9.Restful认识
Restful是一种面向资源的架构风格,可以简单理解为:使用URL定位资源,用HTTP动词(GET,POST,DELETE,PUT)描述操作。 基于Restful API ES和所有客户端的交互都是使用JSON格式的数据,其他所有程序语言都可以使用RESTful API,通过9200端口的与ES进行通信
用户做crud
Get http://localhost:8080/employee/1
Get http://localhost:8080/employees
put http://localhost:8080/employee
delete http://localhost:8080/employee/1
Post http://localhost:8080/employee/1
使用Restful的好处:透明性,暴露资源存在。充分利用 HTTP 协议本身语义,不同请求方式进行不同的操作
10.查询操作
10.1 查询当前类型中的所有文档 _search
格式: GET /索引名称/类型/_search
举例: GET /es_db/_doc/_search
SQL: select * from student
10.2 条件查询, 如要查询age等于28岁的 _search?q=:**
格式: GET /索引名称/类型/_search?q=:**
举例: GET /es_db/_doc/_search?q=age:28
SQL: select * from student where age = 28
10.3 范围查询, 如要查询age在25至26岁之间的 _search?q=*[ TO **] 注意: TO 必须为大写
格式: GET /索引名称/类型/_search?q=***[25 TO 26]
举例: GET /es_db/_doc/_search?q=age[25 TO 26]
SQL: select * from student where age between 25 and 26
10.4 根据多个ID进行批量查询 _mget
格式: GET /索引名称/类型/_mget
举例: GET /es_db/_doc/_mget
“ids”:[“1”,“2”]
SQL: select * from student where id in (1,2)
10.5 查询年龄小于等于28岁的 :<=
格式: GET /索引名称/类型/_search?q=age:<=**
举例: GET /es_db/_doc/_search?q=age:<=28
SQL: select * from student where age <= 28
10.6 查询年龄大于28前的 :>
格式: GET /索引名称/类型/_search?q=age:>**
举例: GET /es_db/_doc/_search?q=age:>28
SQL: select * from student where age > 28
10.7 分页查询 from=&size=
格式: GET /索引名称/类型/_search?q=age[25 TO 26]&from=0&size=1
举例: GET /es_db/_doc/_search?q=age[25 TO 26]&from=0&size=1
SQL: select * from student where age between 25 and 26 limit 0, 1
10.8 对查询结果只输出某些字段 _source=字段,字段
格式: GET /索引名称/类型/_search?_source=字段,字段
举例: GET /es_db/_doc/_search?_source=name,age
SQL: select name,age from student
10.9 对查询结果排序 sort=字段:desc/asc
格式: GET /索引名称/类型/_search?sort=字段 desc
举例: GET /es_db/_doc/_search?sort=age:desc
SQL: select * from student order by age desc
11.文档批量操作
1.批量获取文档数据
批量获取文档数据是通过_mget的API来实现的
(1)在URL中不指定index和type
请求方式:GET
请求地址:_mget
功能说明 : 可以通过ID批量获取不同index和type的数据
请求参数:
docs : 文档数组参数
_index : 指定index
_type : 指定type
_id : 指定id
_source : 指定要查询的字段
GET _mget
"docs": [
"_index": "es_db",
"_type": "_doc",
"_id": 1
,
"_index": "es_db",
"_type": "_doc",
"_id": 2
]
响应结果如下:
"docs" : [
"_index" : "es_db",
"_type" : "_doc",
"_id" : "1",
"_version" : 3,
"_seq_no" : 7,
"_primary_term" : 1,
"found" : true,
"_source" :
"name" : "张三666",
"sex" : 1,
"age" : 25,
"address" : "广州天河公园",
"remark" : "java developer"
,
"_index" : "es_db",
"_type" : "_doc",
"_id" : "2",
"_version" : 1,
"_seq_no" : 1,
"_primary_term" : 1,
"found" : true,
"_source" :
"name" : "李四",
"sex" : 1,
"age" : 28,
"address" : "广州荔湾大厦",
"remark" : "java assistant"
]
(2)在URL中指定index
请求方式:GET
请求地址:/indexName/_mget
功能说明 : 可以通过ID批量获取不同index和type的数据
请求参数:
docs : 文档数组参数
_index : 指定index
_type : 指定type
_id : 指定id
_source : 指定要查询的字段
GET /es_db/_mget
"docs": [
"_type":"_doc",
"_id": 3
,
"_type":"_doc",
"_id": 4
]
(3)在URL中指定index和type
请求方式:GET
请求地址:/indexName/typeName/_mget
功能说明 : 可以通过ID批量获取不同index和type的数据
请求参数:
docs : 文档数组参数
_index : 指定index
_type : 指定type
_id : 指定id
_source : 指定要查询的字段
GET /es_db/_doc/_mget
"docs": [
"_id": 1
,
"_id": 2
]
2.批量操作文档数据
批量对文档进行写操作是通过_bulk的API来实现的
请求方式:POST
请求地址:_bulk
请求参数:通过_bulk操作文档,一般至少有两行参数(或偶数行参数)
第一行参数为指定操作的类型及操作的对象(index,type和id)
第二行参数才是操作的数据
参数类似于:
"actionName":"_index":"indexName", "_type":"typeName","_id":"id"
"field1":"value1", "field2":"value2"
actionName:表示操作类型,主要有create,index,delete和update
(1)批量创建文档create
POST _bulk
"create":"_index":"article", "_type":"_doc", "_id":3
"id":3,"title":"老师1","content":"666","tags":["java", "面向对象"],"create_time":1554015482530
"create":"_index":"article", "_type":"_doc", "_id":4
"id":4,"title":"老师2","content":"NB","tags":["java", "面向对象"],"create_time":1554015482530
(2)普通创建或全量替换index
POST _bulk
"index":"_index":"article", "_type":"_doc", "_id":3
"id":3,"title":"老师(一)","content":"666","tags":["java", "面向对象"],"create_time":1554015482530
"index":"_index":"article", "_type":"_doc", "_id":4
"id":4,"title":"老师(二)","content":"NB","tags":["java", "面向对象"],"create_time":1554015482530
如果原文档不存在,则是创建
如果原文档存在,则是替换(全量修改原文档)
(3)批量删除delete
POST _bulk
"delete":"_index":"article", "_type":"_doc", "_id":3
"delete":"_index":"article", "_type":"_doc", "_id":4
(4)批量修改update
POST _bulk
"update":"_index":"article", "_type":"_doc", "_id":3
"doc":"title":"ES大法必修内功"
"update":"_index":"article", "_type":"_doc", "_id":4
"doc":"create_time":1554018421008
12.DSL语言高级查询
1.Query DSL概述
Domain Specific Language
领域专用语言
Elasticsearch provides a ful1 Query DSL based on JSON to define queries
Elasticsearch提供了基于JSON的DSL来定义查询。
DSL由叶子查询子句和复合查询子句两种子句组成。
2.无查询条件
无查询条件是查询所有,默认是查询所有的,或者使用match_all表示所有
GET /es_db/_doc/_search
"query":
"match_all":
3.有查询条件
3.1 叶子条件查询(单字段查询条件)
3.1.1 模糊匹配
模糊匹配主要是针对文本类型的字段,文本类型的字段会对内容进行分词,对查询时,也会对搜索条件进行分词,然后通过倒排索引查找到匹配的数据,模糊匹配主要通过match等参数来实现
match : 通过match关键词模糊匹配条件内容
prefix : 前缀匹配
regexp : 通过正则表达式来匹配数据
match的复杂用法
match条件还支持以下参数:
query : 指定匹配的值
operator : 匹配条件类型
and : 条件分词后都要匹配
or : 条件分词后有一个匹配即可(默认)
minmum_should_match : 指定最小匹配的数量
3.1.2 精确匹配
term : 单个条件相等
terms : 单个字段属于某个值数组内的值
range : 字段属于某个范围内的值
exists : 某个字段的值是否存在
ids : 通过ID批量查询
3.2 组合条件查询(多条件查询)
组合条件查询是将叶子条件查询语句进行组合而形成的一个完整的查询条件
bool : 各条件之间有and,or或not的关系
must : 各个条件都必须满足,即各条件是and的关系
should : 各个条件有一个满足即可,即各条件是or的关系
must_not : 不满足所有条件,即各条件是not的关系
filter : 不计算相关度评分,它不计算_score即相关度评分,效率更高
constant_score : 不计算相关度评分
must/filter/shoud/must_not 等的子条件是通过 term/terms/range/ids/exists/match 等叶子条件为参数的
注:以上参数,当只有一个搜索条件时,must等对应的是一个对象,当是多个条件时,对应的是一个数组
3.3 连接查询(多文档合并查询)
父子文档查询:parent/child
嵌套文档查询: nested
3.4 DSL查询语言中存在两种:查询DSL(query DSL)和过滤DSL(filter DSL)
它们两个的区别如下图:
query DSL
在查询上下文中,查询会回答这个问题——“这个文档匹不匹配这个查询,它的相关度高么?”
如何验证匹配很好理解,如何计算相关度呢?ES中索引的数据都会存储一个_score分值,分值越高就代表越匹配。另外关于某个搜索的分值计算还是很复杂的,因此也需要一定的时间。
filter DSL
在过滤器上下文中,查询会回答这个问题——“这个文档匹不匹配?”
答案很简单,是或者不是。它不会去计算任何分值,也不会关心返回的排序问题,因此效率会高一点。
过滤上下文 是在使用filter参数时候的执行环境,比如在bool查询中使用must_not或者filter
另外,经常使用过滤器,ES会自动的缓存过滤器的内容,这对于查询来说,会提高很多性能。
3.5 Query方式查询:案例
根据名称精确查询姓名 term, term查询不会对字段进行分词查询,会采用精确匹配
注意: 采用term精确查询, 查询字段映射类型属于为keyword.
举例:
POST /es_db/_doc/_search
"query":
"term":
"name": "admin"
SQL: select * from student where name = 'admin'
根据备注信息模糊查询 match, match会根据该字段的分词器,进行分词查询
举例:
POST /es_db/_doc/_search
"from": 0,
"size": 2,
"query":
"match":
"address": "广州"
SQL: select * from user where address like '%广州%' limit 0, 2
多字段模糊匹配查询与精准查询 multi_match
POST /es_db/_doc/_search
"query":
"multi_match":
"query":"张三",
"fields":["address","name"]
SQL: select * from student where name like '%张三%' or address like '%张三%'
未指定字段条件查询 query_string , 含 AND 与 OR 条件
POST /es_db/_doc/_search
"query":
"query_string":
"query":"广州 OR 长沙"
指定字段条件查询 query_string , 含 AND 与 OR 条件
POST /es_db/_doc/_search
"query":
"query_string":
"query":"admin OR 长沙",
"fields":["name","address"]
范围查询
注:json请求字符串中部分字段的含义
range:范围关键字
gte 大于等于
lte 小于等于
gt 大于
lt 小于
now 当前时间
POST /es_db/_doc/_search
"query" :
"range" :
"age" :
"gte":25,
"lte":28
SQL: select * from user where age between 25 and 28
分页、输出字段、排序综合查询
POST /es_db/_doc/_search
"query" :
"range" :
"age" :
"gte":25,
"lte":28
,
"from": 0,
"size": 2,
"_source": ["name", "age", "book"],
"sort": "age":"desc"
3.6 Filter过滤器方式查询
它的查询不会计算相关性分值,也不会对结果进行排序, 因此效率会高一点,查询的结果可以被缓存。
Filter Context 对数据进行过滤
POST /es_db/_doc/_search
"query" :
"bool" :
"filter" :
"term":
"age":25
总结:
-
match:模糊匹配,需要指定字段名,但是输入会进行分词,比如"hello world"会进行拆分为hello和world,然后匹配,如果字段中包含hello或者world,或者都包含的结果都会被查询出来,也就是说match是一个部分匹配的模糊查询。查询条件相对来说比较宽松。
-
term: 这种查询和match在有些时候是等价的,比如我们查询单个的词hello,那么会和match查询结果一样,但是如果查询"hello world",结果就相差很大,因为这个输入不会进行分词,就是说查询的时候,是查询字段分词结果中是否有"hello world"的字样,而不是查询字段中包含"hello world"的字样。当保存数据"hello world"时,elasticsearch会对字段内容进行分词,“hello world"会被分成hello和world,不存在"hello world”,因此这里的查询结果会为空。这也是term查询和match的区别。
-
match_phase:会对输入做分词,但是需要结果中也包含所有的分词,而且顺序要求一样。以"hello world"为例,要求结果中必须包含hello和world,而且还要求他们是连着的,顺序也是固定的,hello that world不满足,world hello也不满足条件。
-
query_string:和match类似,但是match需要指定字段名,query_string是在所有字段中搜索,范围更广泛。
13.文档映射
ES中映射可以分为动态映射和静态映射
1.动态映射
在关系数据库中,需要事先创建数据库,然后在该数据库下创建数据表,并创建表字段、类型、长度、主键等,最后才能基于表插入数据。而Elasticsearch中不需要定义Mapping映射(即关系型数据库的表、字段等),在文档写入Elasticsearch时,会根据文档字段自动识别类型,这种机制称之为动态映射。
动态映射规则如下:
1 动态映射
1.1 删除原创建的索引
DELETE /es_db
1.2 创建索引
PUT /es_db
1.3 创建文档(ES根据数据类型, 会自动创建映射)
PUT /es_db/_doc/1
"name": "Jack",
"sex": 1,
"age": 25,
"book": "java精通",
"address": "广州"
1.4 获取文档映射
GET /es_db/_mapping
2.静态映射
静态映射是在Elasticsearch中也可以事先定义好映射,包含文档的各字段类型、分词器等,这种方式称之为静态映射。
2.1 删除原创建的索引
DELETE /es_db
2.2 创建索引
PUT /es_db
2.3 设置文档映射
PUT /es_db
"mappings":
"properties":
"name":"type":"keyword","index":true,"store":true,
"sex":"type":"integer","index":true,"store":true,
"age":"type":"integer","index":true,"store":true,
"book":"type":"text","index":true,"store":true,
"address":"type":"text","index":true,"store":true
2.4 根据静态映射创建文档
PUT /es_db/_doc/1
"name": "Jack",
"sex": 1,
"age": 25,
"book": "elasticSearch入门至精通",
"address": "广州车陂"
2.5 获取文档映射
GET /es_db/_mapping
14.核心类型(Core datatype)
字符串:string,string类型包含 text 和 keyword。
text:该类型被用来索引长文本,在创建索引前会将这些文本进行分词,转化为词的组合,建立索引;允许es来检索这些词,text类型不能用来排序和聚合。
keyword:该类型不能分词,可以被用来检索过滤、排序和聚合,keyword类型不可用text进行分词模糊检索。
数值型:long、integer、short、byte、double、float
日期型:date
布尔型:boolean
15.keyword 与 text 映射类型的区别
将 book 字段设置为 keyword 映射 (只能精准查询, 不能分词查询,能聚合、排序)
POST /es_db/_doc/_search
"query":
"term":
"book": "elasticSearch入门至精通"
将 book 字段设置为 text 映射能模糊查询, 能分词查询,不能聚合、排序)
POST /es_db/_doc/_search
"query":
"match":
"book": "elasticSearch入门至精通"
16.创建静态映射时指定text类型的ik分词器
1.设置ik分词器的文档映射
先删除之前的es_db
再创建新的es_db
定义ik_smart的映射
PUT /es_db
"mappings":
"properties":
"name":"type":"keyword","index":true,"store":true,
"sex":"type":"integer","index":true,"store":true,
"age":"type":"integer","index":true,"store":true,
"book":"type":"text","index":true,"store":true,"analyzer":"ik_smart","search_analyzer":"ik_smart",
"address":"type":"text","index":true,"store":true
2.分词查询
POST /es_db/_doc/_search
"query":
"match": "address": "广"
POST /es_db/_doc/_search
"query":
"match": "address": "广州"
17.对已存在的mapping映射进行修改
具体方法
1)如果要推倒现有的映射, 你得重新建立一个静态索引
2)然后把之前索引里的数据导入到新的索引里
3)删除原创建的索引
4)为新索引起个别名, 为原索引名
POST _reindex
"source":
"index": "db_index"
,
"dest":
"index": "db_index_2"
DELETE /db_index
PUT /db_index_2/_alias/db_index
注意: 通过这几个步骤就实现了索引的平滑过渡,并且是零停机
18.Elasticsearch乐观并发控制
在数据库领域中,有两种方法来确保并发更新,不会丢失数据:
1、悲观并发控制
这种方法被关系型数据库广泛使用,它假定有变更冲突可能发生,因此阻塞访问资源以防止冲突。 一个典型的例子是读取一行数据之前先将其锁住,确保只有放置锁的线程能够对这行数据进行修改。
2、乐观并发控制
Elasticsearch 中使用的这种方法假定冲突是不可能发生的,并且不会阻塞正在尝试的操作。 然而,如果源数据在读写当中被修改,更新将会失败。应用程序接下来将决定该如何解决冲突。 例如,可以重试更新、使用新的数据、或者将相关情况报告给用户。
3、再以创建一个文档为例 ES老版本
PUT /db_index/_doc/1
"name": "Jack",
"sex": 1,
"age": 25,
"book": "Spring Boot 入门到精通",
"remark": "hello world"
4、实现_version乐观锁更新文档
PUT /db_index/_doc/1?version=1
"name": "Jack",
"sex": 1,
"age": 25,
"book": "Spring Boot 入门到精通",
"remark": "hello world"
5、ES新版本(7.x)不使用version进行并发版本控制 if_seq_no=版本值&if_primary_term=文档位置
_seq_no:文档版本号,作用同_version
_primary_term:文档所在位置
POST /es_sc/_search
DELETE /es_sc
POST /es_sc/_doc/1
"id": 1,
"name": "大帅比",
"desc": "大帅比",
"create_date": "2022-02-24"
POST /es_sc/_update/1
"doc":
"name": "大帅比666"
POST /es_sc/_update/1/?if_seq_no=1&if_primary_term=1
"doc":
"name": "大帅比1"
POST /es_sc/_update/1/?if_seq_no=1&if_primary_term=1
"doc":
"name": "大帅比2"
19.Java API操作ES
参考实际代码讲解
20.ES集群环境搭建
1.将安装包分发到其他服务器上面
2.修改elasticsearch.yml
node1.baiqi.cn 服务器使用baiqi用户来修改配置文件
mkdir -p /usr/local/es/elasticsearch-7.6.1/log
mkdir -p /usr/local/es/elasticsearch-7.6.1/data
cd /usr/local/es/elasticsearch-7.6.1/config
rm -rf elasticsearch.yml
vim elasticsearch.yml
cluster.name: baiqi-es
node.name: node1.baiqi.cn
path.data: /usr/local/es/elasticsearch-7.6.1/data
path.logs: /usr/local/es/elasticsearch-7.6.1/log
network.host: node1.baiqi.cn
http.port: 9200
discovery.seed_hosts: ["IP1", "IP2", "IP3"]
cluster.initial_master_nodes: ["节点1名称", "节点2名称", "节点3名称"]
bootstrap.system_call_filter: false
bootstrap.memory_lock: false
http.cors.enabled: true
http.cors.allow-origin: "*"
3.修改jvm.option
修改jvm.option配置文件,调整jvm堆内存大小
node1.baiqi.cn使用baiqi用户执行以下命令调整jvm堆内存大小,每个人根据自己服务器的内存大小来进行调整。
cd /usr/local/es/elasticsearch-7.6.1/config
vim jvm.options
-Xms2g
-Xmx2g
4.node2与node3修改es配置文件
node2.baiqi.cn与node3.baiqi.cn也需要修改es配置文件
node2.baiqi.cn使用baiqi用户执行以下命令修改es配置文件
mkdir -p /usr/local/es/elasticsearch-7.6.1/log
mkdir -p /usr/local/es/elasticsearch-7.6.1/data
cd /usr/local/es/elasticsearch-7.6.1/config
vim elasticsearch.yml
cluster.name: baiqi-es
node.name: node2.baiqi.cn
path.data: /usr/local/es/elasticsearch-7.6.1/data
path.logs: /usr/local/es/elasticsearch-7.6.1/log
network.host: node2.baiqi.cn
http.port: 9200
discovery.seed_hosts: ["IP1", "IP2", "IP3"]
cluster.initial_master_nodes: ["节点1名称", "节点2名称", "节点3名称"]
boo以上是关于ElasticSearch的主要内容,如果未能解决你的问题,请参考以下文章
three.js入门-一些基础理论|大帅老猿threejs特训
three.js入门-一些基础理论|大帅老猿threejs特训
有多少漏洞都会重来:从ElasticSearch到MongoDB和Redis