笔记来源于学习 b站中的【IT李老师】的elasticsearch课程 + 自己在实习做的es模块中的理解。
后续会有 中,下篇笔记更新,目前这一篇是上篇。
目录
Elastic Stack简介
1.1简介
1.2特色
1.3组件介绍
2.Elasticsearch的接收与核心概念
2.1搜索是什么
2.2 数据库做搜索弊端
2.2.1站内搜索(垂直搜索):数据量小,简单搜索,可以使用数据库。
2.2.2互联网搜索,肯定不会使用数据库搜索。数据量太大。PB级。
2.3全文检索、倒排索引和Lucene
全文检索
2.4Elasticsearch
Elasticsearch的功能
Elasticsearch的特点
2.5 elasticsearch核心概念
2.5.1 lucene和elasticsearch的关系
2.5.2 elasticsearch的核心概念(重点)
2.5.3 elasticsearch核心概念 vs. 数据库核心概念
3. Elasticsearch相关软件安装
3.1. Windows安装elasticsearch
1、安装JDK,至少1.8.0_73以上版本,验证:java -version。
2、下载和解压缩Elasticsearch安装包,查看目录结构。
3、配置文件
4、启动Elasticsearch:bin\elasticsearch.bat,es的特点就是开箱即,无需配置,启动即可。
5、检查ES是否启动成功:浏览器访问http://localhost:9200
6、浏览器访问 http://localhost:9200/_cluster/health 查询集群状态
3.2. Windows安装Kibana
4.ES快速入门
4.1. 文档(document)的数据格式
4.2简单的集群管理
4.2.1快速检查集群的健康状况
4.2.2 快速查看集群中有哪些索引
4.2.3 创建和删除索引(含使用java创建索引的代码)
4.3案例:对图书的CRUD操作(document CRUD操作,包含java来操作es的代码)
4.3.1 新建图书索引
4.3.2 新增图书 :新增文档
4.3.3 查询图书:检索文档
4.3.4 修改图书:替换操作
4.3.5 修改图书:更新文档指定字段
4.3.6 删除图书:删除文档
5.文档document入门
5.1es中默认自带字段的解析
5.1.1 _index
5.1.2 _type(es9将彻底删除此字段)
5.1.3 _id(重点)
5.1.4 创建索引时,不同数据放到不同索引中
5.2生成文档id
5.2.1 手动生成id
5.2.2 自动生成id
5.3._source 字段
5.3.1 _source
5.3.2 定制返回字段
5.4. 文档的替换与删除
5.4.1全量替换
5.4.2删除
5.5局部替换 partial update
全量替换与局部更新的内部原理
5.8es中的悲观锁与乐观锁机制
图解es内部并发控制
Elastic Stack简介
1.1简介
ELK是一个免费开源的日志分析架构技术栈总称,官网免费且开放的搜索:Elasticsearch、ELK 和 Kibana 的开发者 | Elastic我们是 Elastic (ELK) Stack——Elasticsearch、Kibana、Beats 和 Logstash——的开发者。安全又可靠地搜索、分析和可视化您的数据,无论在云中,还是使用本地部署。https://www.elastic.co/cn。包含三大基础组件,分别是Elasticsearch、Logstash、Kibana。但实际上ELK不仅仅适用于日志分析,它还可以支持其它任何数据搜索、分析和收集的场景,日志分析和收集只是更具有代表性。 并非唯一性。
随着elk的发展,又有新成员Beats、elastic cloud的加入,所以就形成了Elastic Stack。所以说,ELK是旧的称呼,Elastic Stack是新的名字。
1.2特色
-
处理方式灵活:elasticsearch是目前最流行的准实时全文检索引擎,具有高速检索大数据的能力。
-
配置简单:安装elk的每个组件,仅需配置每个组件的一个配置文件即可。修改处不多,因为大量参数已经默认配在系统中,修改想要修改的选项即可。
-
接口简单:采用json形式RESTFUL API接受数据并响应,无关语言。
-
性能高效:elasticsearch基于优秀的全文搜索技术Lucene,采用倒排索引,可以轻易地在百亿级别数据量下,搜索出想要的内容,并且是秒级响应。
-
灵活扩展:elasticsearch和logstash都可以根据集群规模线性拓展,elasticsearch内部自动实现集群协作。
-
数据展现华丽:kibana作为前端展现工具,图表华丽,配置简单。
1.3组件介绍
Elasticsearch
Elasticsearch 是使用java开发,基于Lucene、分布式、通过Restful方式进行交互的近实时搜索平台框架。它的特点有:分布式,零配置,自动发现,索引自动分片,索引副本机制,restful风格接口,多数据源,自动搜索负载等。
Logstash
Logstash 基于java开发,是一个数据抽取转化工具。一般工作方式为c/s架构,client端安装在需要收集信息的主机上,server端负责将收到的各节点日志进行过滤、修改等操作在一并发往elasticsearch或其他组件上去。
Kibana
Kibana 基于nodejs,也是一个开源和免费的可视化工具。Kibana可以为 Logstash 和 ElasticSearch 提供的日志分析友好的 Web 界面,可以汇总、分析和搜索重要数据日志。
Beats
Beats 平台集合了多种单一用途数据采集器。它们从成百上千或成千上万台机器和系统向 Logstash 或 Elasticsearch 发送数据。
Beats由如下组成:
Packetbeat:轻量型网络数据采集器,用于深挖网线上传输的数据,了解应用程序动态。Packetbeat 是一款轻量型网络数据包分析器,能够将数据发送至 Logstash 或 Elasticsearch。其支 持ICMP (v4 and v6)、DNS、HTTP、Mysql、PostgreSQL、Redis、MongoDB、Memcache等协议。
Filebeat:轻量型日志采集器。当您要面对成百上千、甚至成千上万的服务器、虚拟机和容器生成的日志时,请告别 SSH 吧。Filebeat 将为您提供一种轻量型方法,用于转发和汇总日志与文件,让简单的事情不再繁杂。
Metricbeat :轻量型指标采集器。Metricbeat 能够以一种轻量型的方式,输送各种系统和服务统计数据,从 CPU 到内存,从 Redis 到 Nginx,不一而足。可定期获取外部系统的监控指标信息,其可以监控、收集 Apache http、HAProxy、MongoDB、MySQL、Nginx、PostgreSQL、Redis、System、Zookeeper等服务。
Winlogbeat:轻量型 Windows 事件日志采集器。用于密切监控基于 Windows 的基础设施上发生的事件。Winlogbeat 能够以一种轻量型的方式,将 Windows 事件日志实时地流式传输至 Elasticsearch 和 Logstash。
Auditbeat:轻量型审计日志采集器。收集您 Linux 审计框架的数据,监控文件完整性。Auditbeat 实时采集这些事件,然后发送到 Elastic Stack 其他部分做进一步分析。
Heartbeat:面向运行状态监测的轻量型采集器。通过主动探测来监测服务的可用性。通过给定 URL 列表,Heartbeat 仅仅询问:网站运行正常吗?Heartbeat 会将此信息和响应时间发送至 Elastic 的其他部分,以进行进一步分析。
Functionbeat:面向云端数据的无服务器采集器。在作为一项功能部署在云服务提供商的功能即服务 (FaaS) 平台上后,Functionbeat 即能收集、传送并监测来自您的云服务的相关数据。
Elastic cloud
基于 Elasticsearch 的软件即服务(SaaS)解决方案。通过 Elastic 的官方合作伙伴使用托管的 Elasticsearch 服务。
2.Elasticsearch的接收与核心概念
2.1搜索是什么
概念:用户输入想要的关键词,返回含有该关键词的【所有信息】。
场景:
1互联网搜索:谷歌、百度、各种新闻首页
2 站内搜索(垂直搜索):企业OA查询订单、人员、部门,电商网站内部搜索商品(淘宝、京东)场景。
2.2 数据库做搜索弊端
2.2.1站内搜索(垂直搜索):数据量小,简单搜索,可以使用数据库。
问题出现:
-
存储问题。电商网站商品上亿条时,涉及到单表数据过大必须拆分表,数据库磁盘占用过大必须分库(mycat)。
-
性能问题:即便解决上面的问题,但是查询“笔记本电脑”等关键词时,上亿条数据的商品名字段逐行扫描,性能跟不上。
-
不能分词。如搜索“笔记本电脑”,只能搜索完全和关键词一样的数据,那么数据量小时,搜索“笔记电脑”,“电脑”数据要不要给用户。
2.2.2互联网搜索,肯定不会使用数据库搜索。数据量太大。PB级。
2.3全文检索、倒排索引和Lucene
全文检索
倒排索引。数据存储时,经行分词建立term索引库。 --- > 相当于天然分表了,虽然对数据进行分词会消耗内存,但是当数据量足够大的时候,实际上分词的数量就会变得有限了(减少磁盘存储),天然分词。
通过检索词在倒排索引表中获取到相关的信息标识(比如数据id),然后通过这个信息标识(比如数据id)去原表中查询的这一个过程就叫做全文检索。
倒排索引源于实际应用中需要根据属性的值来查找记录(通过值去找数据id,然后再通过id找到需要的数据)。这种索引表中的每一项都包括一个属性值和具有该属性值的各记录的地址。由于不是由记录来确定属性值,而是由属性值来确定记录的位置,因而称为倒排索引(inverted index)。带有倒排索引的文件我们称为【倒排索引文件】,简称【倒排文件】(inverted file)。
例如:
Lucene
就是一个jar包,里面封装了全文检索的引擎、搜索的算法代码。开发时,引入lucene的jar包,通过api开发搜索相关业务。底层会在磁盘建立索引库。
Lucene不支持分布式,会产生很多问题:比如 当启动Lucene的服务器存储的数据到达最大量了要对服务器进行扩融,此时数据如何分布?数据如何交互?数据怎么备份? 这些都是Lucene中的问题,es就把这些问题给解决了。
那么es是怎么解决这些问题的?
-
数据分布 通过分片机制,同一个集群下的所有服务器都是属于同一个片区
-
平行节点,内部交互
-
副本机制进行数据备份
-
高级搜索 count group By
2.4Elasticsearch
Elasticsearch的功能
-
分布式的搜索引擎和数据分析引擎
搜索:互联网搜索、电商网站站内搜索、OA系统查询
数据分析:电商网站查询近一周哪些品类的图书销售前十;新闻网站,最近3天阅读量最高的十个关键词,舆情分析。
-
全文检索,结构化检索,数据分析
全文检索:搜索商品名称包含java的图书select * from books where book_name like "%java%"。
结构化检索:搜索商品分类为spring的图书都有哪些,select * from books where name = 'spring'
数据分析:分析每一个分类下有多少种图书,select category_id,count(*) from books group by category_id
-
对海量数据进行近实时的处理
分布式:ES自动可以将海量数据分散到多台服务器(代表可以利用多台服务器的cpu和系统资源来完成搜索)上去存储和检索,经行并行查询,提高搜索效率。相对的,Lucene是单机应用。
近实时:数据库上亿条数据查询,搜索一次耗时几个小时,是批处理(batch-processing)。而es只需秒级即可查询海量数据,所以叫近实时。秒级。
Elasticsearch的特点
-
可拓展性:大型分布式集群(数百台服务器)技术,处理PB级数据,大公司可以使用。小公司数据量小,也可以部署在单机。大数据领域使用广泛。
-
技术整合:将全文检索、数据分析、分布式相关技术整合在一起:lucene(全文检索),商用的数据分析软件(BI软件),分布式数据库(mycat)
-
部署简单:开箱即用,很多默认配置不需关心,解压完成直接运行即可。拓展时,只需多部署几个实例即可,负载均衡、分片迁移集群内部自己实施。
-
接口简单:使用restful api经行交互,跨语言。
-
功能强大:Elasticsearch作为传统数据库的一个补充,提供了数据库所不不能提供的很多功能,如全文检索,同义词处理,相关度排名。
2.5 elasticsearch核心概念
2.5.1 lucene和elasticsearch的关系
Lucene:最先进、功能最强大的搜索库,直接基于lucene开发,非常复杂,api复杂
Elasticsearch:基于lucene,封装了许多lucene底层功能,提供简单易用的restful api接口和许多语言的客户端,如java的高级客户端(Java High Level REST Client)和底层客户端(Java Low Level REST Client)
起源:Shay Banon。2004年失业,陪老婆去伦敦学习厨师。失业在家帮老婆写一个菜谱搜索引擎。封装了lucene的开源项目,compass。找到工作后,做分布式高性能项目,再封装compass,写出了elasticsearch,使得lucene支持分布式。现在是Elasticsearch创始人兼Elastic首席执行官。
2.5.2 elasticsearch的核心概念(重点)
1 NRT(Near Realtime):近实时
两方面:
-
写入数据时,过1秒才会被搜索到,因为内部在分词、录入索引。
-
es搜索时:搜索和分析数据需要秒级出结果。
2 Cluster:集群
包含一个或多个启动着es实例的机器群。通常一台机器起一个es实例。同一网络下,如果集群名一样,那么多个es实例会自动组成集群,自动均衡分片等行为。默认集群名为“elasticsearch”。
3 Node:节点
每个es实例称为一个节点。节点名自动分配,也可以手动配置。
4 Index:索引
包含一堆有相似结构的文档数据。
索引创建规则:
-
仅限小写字母
-
不能包含\、/、 *、?、"、<、>、|、#以及空格符等特殊符号
-
从7.0版本开始不再包含冒号
-
不能以-、_或+开头
-
不能超过255个字节(注意它是字节,因此多字节字符将计入255个限制)
5 Document:文档
es中的最小数据单元。一个document就像数据库中的一条记录。通常以json格式显示。多个document存储于一个索引(Index)中。
book document
{
"book_id": "1",
"book_name": "java编程思想",
"book_desc": "从Java的基础语法到最高级特性(深入的[面向对象](https://baike.baidu.com/item/面向对象)概念、多线程、自动项目构建、单元测试和调试等),本书都能逐步指导你轻松掌握。",
"category_id": "2",
"category_name": "java"
}
6 Field:字段
就像数据库中的列(Columns),定义每个document应该有的字段。
7 Type:类型
每个索引里都可以有一个或多个type,type是index中的一个逻辑数据分类,一个type下的document,都有相同的field。
注意:6.0之前的版本有type(类型)概念,type相当于关系数据库的表,ES官方将在ES9.0版本中彻底删除type。笔记中的代码中的typy都为_doc。
8 shard:分片
index数据过大时,【将index里面的数据,分为多个shard】,分布式的存储在各个服务器上面。可以支持海量数据和高并发,提升性能和吞吐量,充分利用多台机器的cpu。
优点:减轻单节点的压力,充分利用机器的性能,方便集群拓展
9 replica:副本
在分布式环境下,任何一台机器都会随时宕机,如果宕机,index的一个分片没有,导致此index不能搜索。所以,为了保证数据的安全,我们会将每个index的分片经行备份,存储在另外的机器上。保证少数机器宕机es集群仍可以搜索。
能正常提供查询和插入的分片我们叫做主分片(primary shard),其余的我们就管他们叫做备份的分片(replica shard)。
es6默认新建索引时,5分片,2副本,也就是一主一备,共10个分片。所以,es集群最小规模为两台。
2.5.3 elasticsearch核心概念 vs. 数据库核心概念
关系型数据库(比如Mysql) | 非关系型数据库(Elasticsearch) |
---|---|
数据库Database | 索引Index |
表Table | 索引Index(原为Type) |
数据行Row | 文档Document |
数据列Column | 字段Field |
约束 Schema | 映射Mapping |
3. Elasticsearch相关软件安装
3.1. Windows安装elasticsearch
1、安装JDK,至少1.8.0_73以上版本,验证:java -version。
2、下载和解压缩Elasticsearch安装包,查看目录结构。
Download Elasticsearch | ElasticDownload Elasticsearch or the complete Elastic Stack (formerly ELK stack) for free and start searching and analyzing in minutes with Elastic.https://www.elastic.co/cn/downloads/elasticsearch
bin:脚本目录,包括:启动、停止等可执行脚本
config:配置文件目录
data:索引目录,存放索引文件的地方
logs:日志目录
modules:模块目录,包括了es的功能模块
plugins :插件目录,es支持插件机制
3、配置文件
位置:ES的配置文件的地址根据安装形式的不同而不同:
使用zip、tar安装,配置文件的地址在安装目录的config下。
使用RPM安装,配置文件在/etc/elasticsearch下。
使用MSI安装,配置文件的地址在安装目录的config下,并且会自动将config目录地址写入环境变量ES_PATH_CONF。
elasticsearch.yml
配置格式是YAML,可以采用如下两种方式:
方式1:层次方式
path:
data: /var/lib/elasticsearch
logs: /var/log/elasticsearch
方式2:属性方式
path.data: /var/lib/elasticsearch
path.logs: /var/log/elasticsearch
常用的配置项如下:(没有特殊要求的话一般都是使用默认的就行)
cluster.name:
配置elasticsearch的集群名称,默认是elasticsearch。建议修改成一个有意义的名称。
node.name:
节点名,通常一台物理服务器就是一个节点,es会默认随机指定一个名字,建议指定一个有意义的名称,方便管理
一个或多个节点组成一个cluster集群,集群是一个逻辑的概念,节点是物理概念,后边章节会详细介绍。
path.conf:
设置配置文件的存储路径,tar或zip包安装默认在es根目录下的config文件夹,rpm安装默认在/etc/ elasticsearch
path.data:
设置索引数据的存储路径,默认是es根目录下的data文件夹,可以设置多个存储路径,用逗号隔开。
path.logs:
设置日志文件的存储路径,默认是es根目录下的logs文件夹
path.plugins:
设置插件的存放路径,默认是es根目录下的plugins文件夹
bootstrap.memory_lock: true
设置为true可以锁住ES使用的内存,避免内存与swap分区交换数据。
network.host:
设置绑定主机的ip地址,设置为0.0.0.0表示绑定任何ip,允许外网访问,生产环境建议设置为具体的ip。
http.port: 9200
设置对外服务的http端口,默认为9200。
transport.tcp.port: 9300 集群结点之间通信端口
node.master:
指定该节点是否有资格被选举成为master结点,默认是true,如果原来的master宕机会重新选举新的master。
node.data:
指定该节点是否存储索引数据,默认为true。
discovery.zen.ping.unicast.hosts: ["host1:port", "host2:port", "..."]
设置集群中master节点的初始列表。
discovery.zen.ping.timeout: 3s
设置ES自动发现节点连接超时的时间,默认为3秒,如果网络延迟高可设置大些。
discovery.zen.minimum_master_nodes:
主结点数量的最少值 ,此值的公式为:(master_eligible_nodes / 2) + 1 ,比如:有3个符合要求的主结点,那么这里要设置为2。
node.max_local_storage_nodes:
单机允许的最大存储结点数,通常单机启动一个结点建议设置为1,开发环境如果单机启动多个节点可设置大于1。
jvm.options
设置最小及最大的JVM堆内存大小:
在jvm.options中设置 -Xms和-Xmx:
1) 两个值设置为相等
2) 将Xmx 设置为不超过物理内存的一半。
log4j2.properties
日志文件设置,ES使用log4j,注意日志级别的配置。
4、启动Elasticsearch:bin\elasticsearch.bat,es的特点就是开箱即,无需配置,启动即可。
下面提供了两种启动方式:
注意:es7 windows版本不支持机器学习,所以elasticsearch.yml中添加如下几个参数:
node.name: node-1
cluster.initial_master_nodes: ["node-1"]
xpack.ml.enabled: false
http.cors.enabled: true #跨域问题相关配置
http.cors.allow-origin: /.*/ #跨域问题相关配置
直接把上面的5个配置复制到:elasticsearch.yml文件的最后就行,然后就可以双击elasticsearch.bat进行运行,可能会出现黑窗口弹出后又被关闭,但是此时es已经在后台启动了。可以先在浏览器试一下看是不是启动成功了。
解释:
name: node名称,取自机器的hostname
cluster_name: 集群名称(默认的集群名称就是elasticsearch)
version.number: 7.17.7,es版本号
version.lucene_version:封装的lucene版本号
如果上面这种方式还是不能启动本地Windows的es,那么就再这样试试:cmd进行es安装目录的bin目录,然后输入:elasticsearch
控制面板可能会报一些错误,不过不影响使用,使用浏览器访问:localhost:9200,看有没有相关的信息显示。此时黑窗口依旧存在,不会关闭。
5、检查ES是否启动成功:浏览器访问http://localhost:9200
6、浏览器访问 http://localhost:9200/_cluster/health 查询集群状态
{
"cluster_name": "elasticsearch",
"status": "green",
"timed_out": false,
"number_of_nodes": 1,
"number_of_data_nodes": 1,
"active_primary_shards": 0,
"active_shards": 0,
"relocating_shards": 0,
"initializing_shards": 0,
"unassigned_shards": 0,
"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": 100
}
Status:集群状态。Green 所有分片可用。Yellow所有主分片可用。Red主分片不可用,集群不可用。
3.2. Windows安装Kibana
1、kibana是es数据的前端展现,数据分析时,可以方便地看到数据。作为开发人员,可以方便访问es。
2、下载,解压kibana。
3、启动Kibana:bin\kibana.bat
4、浏览器访问 http://localhost:5601 进入Dev Tools界面。像plsql一样支持代码提示。
5、发送get请求,查看集群状态 GET _cluster/health。
6、为kibana设置中文显示,打卡安装目录下的config文件,然后打卡里面的配置文件kibana.yml,然后添加下面这一行代码
i18n.locale: "zh-CN"
然后重新启动kibana就行。
4.ES快速入门
4.1. 文档(document)的数据格式
(1)应用系统的数据结构都是面向对象的,具有复杂的数据结构
(2)对象存储到数据库,需要将关联的复杂对象属性插到另一张表,查询时再拼接起来。
(3)es面向文档,文档中存储的数据结构,与对象一致。一个对象可以直接存成一个文档。
(4)es的document用json数据格式来表达。
例如:班级和学生关系
public class Student {
private String id;
private String name;
private String classInfoId;
}
private class ClassInfo {
private String id;
private String className;
//....
}
数据库中要设计 一对多,多对一的两张表,外键等。查询出来时,还要关联,mybatis写映射文件,很繁琐。
而在es中,一个学生存成文档如下:
{
"id":"1",
"name": "张三",
"last_name": "zhang",
"classInfo": {
"id": "1",
"className": "三年二班",
}
}
4.2简单的集群管理
4.2.1快速检查集群的健康状况
GET /_cat/health?v
集群的健康状况:green、yellow、red
- green:每个索引的primary shard和replica shard都是active状态的
- yellow:每个索引的primary shard都是active状态的,但是部分replica shard不是active状态,处于不可用的状态
- red:不是所有索引的primary shard都是active状态的,部分索引有数据丢失了
4.2.2 快速查看集群中有哪些索引
GET /_cat/indices?v
4.2.3 创建和删除索引(含使用java创建索引的代码)
创建索引:PUT /demo_index?pretty 创建一个名叫demo_index的索引
{
"acknowledged" : true,
"shards_acknowledged" : true,
"index" : "demo_index"
}
后面使用java也可以操作: client对象是es连接对象
//判断索引是否存在
GetIndexRequest getIndexRequest = new GetIndexRequest("索引名称");
boolean exists = client.indices().exists(getIndexRequest, RequestOptions.DEFAULT);
//如果不存在,那就创建索引
if (!exists){
CreateIndexRequest request = new CreateIndexRequest("索引名称");
client.indices().create(request, RequestOptions.DEFAULT);
}
删除索引:DELETE /demo_index?pretty
使用java操作删除索引:
//判断索引是否存在 client为连接对象
GetIndexRequest getIndexRequest = new GetIndexRequest("索引名称"); //"索引名称"这个可以用枚举类来表示
boolean exists = client.indices().exists(getIndexRequest, RequestOptions.DEFAULT);
if(exists){
if(data.size()==0 || null==data){
DeleteIndexRequest deleteIndexRequest = new DeleteIndexRequest("索引名称");
client.indices().delete(deleteIndexRequest,RequestOptions.DEFAULT);
}
4.3案例:对图书的CRUD操作(document CRUD操作,包含java来操作es的代码)
4.3.1 新建图书索引
首先建立图书索引 book
语法:put /index
PUT /book
4.3.2 新增图书 :新增文档
语法:PUT /index/type/id
PUT /book/_doc/1
{
"name": "Bootstrap开发",
"description": "Bootstrap是由Twitter推出的一个前台页面开发css框架,是一个非常流行的开发框架,此框架集成了多种页面效果。此开发框架包含了大量的CSS、JS程序代码,可以帮助开发者(尤其是不擅长css页面开发的程序人员)轻松的实现一个css,不受浏览器限制的精美界面css效果。",
"studymodel": "201002",
"price":38.6,
"timestamp":"2019-08-25 19:11:35",
"pic":"group1/M00/00/00/wKhlQFs6RCeAY0pHAAJx5ZjNDEM428.jpg",
"tags": [ "bootstrap", "dev"]
}
PUT /book/_doc/2
{
"name": "java编程思想",
"description": "java语言是世界第一编程语言,在软件开发领域使用人数最多。",
"studymodel": "201001",
"price":68.6,
"timestamp":"2019-08-25 19:11:35",
"pic":"group1/M00/00/00/wKhlQFs6RCeAY0pHAAJx5ZjNDEM428.jpg",
"tags": [ "java", "dev"]
}
也可以使用java来进行操作:
private void createIndex(List<Map<String, Object>> list){
RestHighLevelClient client = null;
try {
//获取es连接对象 自己封装的工具类
client = Util.getClient();
if (list.size() > 0){
BulkRequest request = new BulkRequest();
//把标准目录卡片中的数据导入es中
for (int i = 0;i<list.size();i++){
Map<String, Object> map = list.get(i);
//这里不能直接对获取到的map对象进行修改,必须要创建一个新的map对象来把数据存储进去 否则会报集合修改错误
HashMap<String, Object> res = new HashMap<>();
//这个文档有什么字段就在这里把字段存到map中 ...
res.put("id",map.get("id").toString());
res.put("name",map.get("name").toString())==null?"":map.get("name").toString());
request.timeout(TimeValue.timeValueMinutes(5)).add(new IndexRequest("索引名称").id(res.get("id").toString()).source(res));
}
BulkResponse bulkResponse = client.bulk(request, RequestOptions.DEFAULT);
}
}catch (Exception e){
e.printStackTrace();
}finally {
//把连接对象返回给连接池
Util.returnClient(client);
}
}
4.3.3 查询图书:检索文档
语法:GET /index/type/id
查看图书:GET /book/_doc/1 就可看到json形式的文档。方便程序解析。 数据是存储在source下的。
对应的java搜索代码这里就不放了,后面会有 综合搜索的java代码案例展示。
为方便查看索引中的数据,kibana可以如下操作:
Kibana-discover- Create index pattern- Index pattern填book
下一步,再点击discover就可看到数据。
点击json还可以看到原始数据:
也可以通过这个table来对数据进行过滤:
4.3.4 修改图书:替换操作
这种情况是进行全局替换,需要把每个字段的数据都要进行携带,这样比较麻烦,es中对于这种操作也是先把旧数据标记为删除然后把这个修改后的数据进行新增。
PUT /book/_doc/1
{
"name": "Bootstrap开发教程1",
"description": "Bootstrap是由Twitter推出的一个前台页面开发css框架,是一个非常流行的开发框架,此框架集成了多种页面效果。此开发框架包含了大量的CSS、JS程序代码,可以帮助开发者(尤其是不擅长css页面开发的程序人员)轻松的实现一个css,不受浏览器限制的精美界面css效果。",
"studymodel": "201002",
"price":38.6,
"timestamp":"2019-08-25 19:11:35",
"pic":"group1/M00/00/00/wKhlQFs6RCeAY0pHAAJx5ZjNDEM428.jpg",
"tags": [ "bootstrap", "开发"]
}
这种替换操作是整体覆盖,要带上所有信息。
4.3.5 修改图书:更新文档指定字段
语法:POST /{index}/_update/{id}
POST /book/_update/1/ //可以对指定的字段进行修改更新
{
"doc": {
"name": " Bootstrap开发教程高级"
}
}
private void updateIndex(List<Map<String, Object>> list){
RestHighLevelClient client = null;
try {
//获取es连接对象 自己封装的工具类
client = Util.getClient();
if (list.size() > 0){
BulkRequest request = new BulkRequest();
//把标准目录卡片中的数据导入es中
for (int i = 0;i<list.size();i++){
Map<String, Object> map = list.get(i);
//这里不能直接对获取到的map对象进行修改,必须要创建一个新的map对象来把数据存储进去 否则会报集合修改错误
HashMap<String, Object> res = new HashMap<>();
//要更新的数据字段 并且把新数据存储进来
res.put("id",map.get("id").toString());
res.put("name",map.get("name").toString())==null?"":map.get("name").toString());
request.timeout(TimeValue.timeValueMinutes(5)).add(new UpdateRequest("索引名称",res.get("id").toString()).doc(res));
}
BulkResponse bulkResponse = client.bulk(request, RequestOptions.DEFAULT);
}
}catch (Exception e){
e.printStackTrace();
}finally {
//把连接对象返回给连接池
Util.returnClient(client);
}
}
4.3.6 删除图书:删除文档
语法: DELETE /book/_doc/1 后面跟的是document对应的id,这个id是数据在入es索引的时候你自己指定的id
java操作:
/**
* 删除es中指定的数据
* @param ids document的id标识集合
*/
public void deleteIndexDoc(List<String> ids){
RestHighLevelClient client = null;
if(ids.size()>0){
BulkRequest request = new BulkRequest();
//删除
for(String id:ids){
request.timeout(TimeValue.timeValueMinutes(5)).add(new DeleteRequest("索引名称",id));
}
try {
client = Util.getClient(); //自己封装的获取es连接对象的工具类
client.bulk(request, RequestOptions.DEFAULT);
} catch (Exception e) {
e.printStackTrace();
}finally {
Util.returnClient(client);
}
}
}
5.文档document入门
5.1es中默认自带字段的解析
先看下面的文档信息:
{
"_index" : "book",
"_type" : "_doc",
"_id" : "1",
"_version" : 1,
"_seq_no" : 10,
"_primary_term" : 1,
"found" : true,
"_source" : {
"name" : "Bootstrap开发教程1",
"description" : "Bootstrap是由Twitter推出的一个前台页面开发css框架,是一个非常流行的开发框架,此框架集成了多种页面效果。此开发框架包含了大量的CSS、JS程序代码,可以帮助开发者(尤其是不擅长css页面开发的程序人员)轻松的实现一个css,不受浏览器限制的精美界面css效果。",
"studymodel" : "201002",
"price" : 38.6,
"timestamp" : "2019-08-25 19:11:35",
"pic" : "group1/M00/00/00/wKhlQFs6RCeAY0pHAAJx5ZjNDEM428.jpg",
"tags" : [
"bootstrap",
"开发"
]
}
}
5.1.1 _index
-
含义:此文档属于哪个索引
-
原则:类似数据放在一个索引中。数据库中表的定义规则。如图书信息放在book索引中,员工信息放在employee索引中。各个索引存储和搜索时互不影响。
-
定义规则:英文小写。尽量不要使用特殊字符。order user
5.1.2 _type(es9将彻底删除此字段)
-
含义:类别。book java node
-
注意:以后的es9将彻底删除此字段,所以当前版本在不断弱化type。不需要关注。笔记中见到_type都为doc。
5.1.3 _id(重点)
含义:文档的唯一标识。就像表的id主键。结合索引可以标识和定义一个文档。
生成:手动(put /index/_doc/id)、自动
手动的话,指定数据的唯一字段作为_id就行,一般是使用表的主键id来作为这个 _id ,但是在多表联查的时候可能会导致查询出来的结果中主键id不再唯一,这个时候可以使用联合字段来作为document的 _id 。
5.1.4 创建索引时,不同数据放到不同索引中
可以根据业务需求来创建索引,因为有一些数据是查询频繁,一些数据是几乎不怎么变化,或者是一些数据频繁变化,这些应该存储在不同的索引中,这样可以保证es的性能。
5.2生成文档id
5.2.1 手动生成id
场景:数据从其他系统导入时,本身有唯一主键(前面的创建文档信息的时候就是通过手动指定id的,指定的Id必须具有唯一性,否则会导致es中的数据被覆盖)。如数据库中的图书、员工信息等。
用法:put /index/_doc/id
PUT /test_index/_doc/1
{
"test_field": "test"
}
5.2.2 自动生成id
用法:POST /index/_doc
POST /test_index/_doc
{
"test_field": "test1"
}
返回:
{
"_index" : "test_index",
"_type" : "_doc",
"_id" : "x29LOm0BPsY0gSJFYZAl",
"_version" : 1,
"result" : "created",
"_shards" : {
"total" : 2,
"successful" : 1,
"failed" : 0
},
"_seq_no" : 0,
"_primary_term" : 1
}
自动id特点:
长度为20个字符,URL安全,base64编码,GUID,分布式生成不冲突
5.3._source 字段
5.3.1 _source
含义:插入数据时的所有字段和值。在get获取数据时,在_source字段中原样返回。
GET /book/_doc/1
5.3.2 定制返回字段
就像sql不要 select *,而要select name,price from book …一样。
GET /book/_doc/1?__source_includes=name,price 只查询 name和price字段的数据 那么返回的source中的数据只有这两个字段
{
"_index" : "book",
"_type" : "_doc",
"_id" : "1",
"_version" : 1,
"_seq_no" : 10,
"_primary_term" : 1,
"found" : true,
"_source" : {
"price" : 38.6,
"name" : "Bootstrap开发教程1"
}
}
5.4. 文档的替换与删除
5.4.1全量替换
执行两次,返回结果中版本号(_version)在不断上升。此过程为全量替换。
PUT /test_index/_doc/1
{
"test_field": "test"
}
实质:旧文档的内容不会立即删除,只是标记为deleted。适当的时机,集群会将这些旧文档删除。
每次对数据进行全量替换,这个version字段的值就会进行加一,这个过程这个旧版本的数据此时并没有被删除,依旧存储在es中,在合适的时机es会自动把这些【标记为删除的数据】(_id相同但是不是最新版本的数据)全部删除,这样可以减少系统的损耗(减少IO操作次数),不可能每来一次更新请求就执行一次删除。
5.4.2删除
DELETE /index/_doc/id
DELETE /test_index/_doc/1/
实质:旧文档的内容不会立即删除,只是标记为deleted。适当的时机(达到一个阈值),集群会将这些文档删除。
lazy delete ---> 减少IO次数
5.5局部替换 partial update
使用 PUT /index/type/id 为文档全量替换,需要将文档所有数据提交。
partial update局部替换则只修改变动字段。
用法: filed是要替换的字段名
post /index/type/id/_update
{
"doc": {
"field":"value"
}
}
全量替换与局部更新的内部原理
内部与全量替换是一样的,旧文档标记为删除,同时新建一个文档。
局部更新优点:
-
大大减少网络传输次数和流量,提升性能 (全局更新java与es进行了三次网络传输,局部更新java与es只进行了一次网络传输)
-
减少并发冲突发生的概率。
如同秒杀,多线程情况下,es同样会出现并发冲突问题(在多线程进行修改数据的时候,会导致其他线程读取的数据不准确)。
5.8es中的悲观锁与乐观锁机制
为控制并发问题,我们通常采用锁机制。分为悲观锁和乐观锁两种机制。
悲观锁:很悲观,所有情况都上锁。此时只有一个线程可以操作数据。具体例子为数据库中的行级锁、表级锁、读锁、写锁等。
特点:优点是方便,直接加锁,对程序透明。缺点是效率低。
乐观锁:很乐观,对数据本身不加锁。提交数据时,通过一种机制验证是否存在冲突,如es中通过版本号验证。
特点:优点是并发能力高。缺点是操作繁琐,在提交数据时,可能反复重试多次。
es中采用的是乐观锁的机制,基于_version字段的版本控制。
图解es内部并发控制
es内部主从同步时,是多线程异步,所以说,当多个请求是乱序的。使用乐观锁机制来进行控制并发。