目录
- 什么是ElasticSearch
- 核心能力
- ES的搜索核心
- 搜索引擎选择
- 搜索的处理
- 补充:
- 小节总结:
- 基本学习环境搭建
- 如何操作ElasticSearch
- 下载、安装和运行(Based Windows)
- 如何操作ES
- 基于postman操作
- 补充:
- 小节总结
- 需要了解的概念
- 分布式模型相关
- 数据存储相关
- 小节总结
- Hello ElasticSearch
- 写->读
- 写->搜索
- 小节总结
发表日期:2019年9月18日
什么是ElasticSearch
ElasticSearch是一个集数据存储、数据搜索和数据分析为一体的系统。它是分布式的,所以能利用分布式来提高其处理能力,具有高可用性和高伸缩性。如果你需要一个能够提供高性能的搜索服务的系统,那么它或许是一个好的选择。
- 数据存储:是指它能够以JSON格式来存储数据。如果你不在意数据的搜索,你甚至可以像类似使用mongodb那样来单纯把它作为一个数据存储系统使用。
- 数据搜索:是指它能够对JSON格式的数据进行全文检索等搜索。
- 数据分析:是指它能够利用一些算法来对JSON文档数据进行分析,比如得出某个月的商品销售增长量。
核心能力
ElasticSearch是一个搜索系统,搜索就是从数据集合中搜索出我们想要的数据,例如从大量的商品数据中搜索出我们想要的某类商品。
现在提一个需求,例如我有一个“文章”的表,我想搜索文章表中字段content中包含有'java'的数据。
如果你不使用ES,那么从开发角度来说,平常我们都是使用关系型数据库系统来存储数据,然后使用类似select name,age,address from student where name like '%李%'
的语句通过模糊匹配来搜索符合指定条件的数据的。(对应到上面的需求应该是select name,author,content from article where content like '%java%'
)但其实上面这种基于模糊匹配的搜索方式的效率是比较低的,因为数据库系统的搜索通常是逐一扫描的,也就是从头到尾的来尝试匹配,某个字段的数据越多,可能需要尝试匹配的次数就会越多(试想一下从4000字的文章中从上到下只为找到一个字),这种查找就好像最低级的遍历查找(当然并不是真的就是傻傻的遍历了,各个数据库系统都会采用各种算法来优化)。
而ElasticSearch由于其内部建立了每个词的索引表,当搜索某个词时,可以根据这个词从索引表中找到匹配的记录,所以效率比较高(就好像记录了某个词的坐标,有了坐标,就能根据坐标非常快地找到那个词)。
(这里举个类似的栗子:相信大家都用过字典,那么普通的数据库搜索就好像从第一页到最后一页找一个词,而ElasticSearch根据这个词的部首结构从“部首-字的对应表”中直接查找到那个字的页数,这个效率直接就是天差地别了!)另外,数据库的搜索是根据指定词直接查找的,它是很笨的!它不能查找到某些意义上“类似”的结果,比如我搜索“mother”,但如果某个记录中包含“mom”这个词,那这条记录也应该被展示出来,而数据库的普通搜索做不到。
而这个操作ElasticSearch就可以做到,由于它内部有分词器,在建立索引的过程中,分词器可以把数据中的某些词都认为是指定的某一个词(比如把mother,mom通通都使用mom作为索引词),再用这个词来建立索引,然后在进行搜索的时候,将输入的词也进行同样的转化,再根据这个词从索引表中查找到符合的记录结果,这样就可以把那些意义相近的结果也搜索出来。所以说,ElasticSearch解决了普通全文搜索的搜索效率低下和搜索不智能的问题。
ES的搜索核心
介绍两个搜索方法:顺序扫描查找、全文搜索
上面有说到数据库的搜索和ElasticSearch的搜索。
常见的关系型数据库的针对某个字段中的数据的搜索是顺序扫描查找,从头到尾去尝试匹配,也就是所谓的遍历查找,当然算法可能没有那么低级。(现在一些数据库系统也在尝试优化全文搜索功能。)而ElasticSearch的搜索是全文搜索,而什么是全文搜索?
全文搜索可以根据一定方式把非结构化的数据对应到一种结构化的标识,从而可以通过标识来检索到指定的非结构化的数据记录。
这句话可能有点难以理解,举个例子理解,比如有一大堆食物你需要去认识,食物本身可以被认作是非结构化的数据,因为他们都是独特的,但如果我们利用他们的颜色来划分的话就可以初步地将他们进行结构化划分,这个就是一种简单的将数据结构化的手段。在ElasticSearch中,这个把非结构化的数据对应到一种结构化的标识的方式就是倒排索引,下面介绍倒排索引来理解这个概念。在ElasticSearch中,处理这些非结构化的数据的方式就是建立倒排索引(Inverted Index)。
什么是倒排索引呢?
倒排索引把数据进行了拆分(比如某个字段的数据为hello world,那么就会被拆分成hello和world),我们使用这些拆分的词来作为索引词来建立索引表,在以hello为索引词的记录中,有对hello world
的指向,world也是如此。
当然,这里的拆分并不是真实的拆分,原始的数据依然存储在elasticsearch中,我们另外创建了一个索引文件来存储。下面是一个使用倒排索引搜索的示例
1.首先,假设我们有一个字段的数据是"I thank my mother",当我们把这个数据存储到ElasticSearch中,ElasticSearch内部使用分词器进行处理数据,分词器用于将非结构化数据中的词进行拆分和转换,于是把"I thank my mother"拆解成了"I"、"thank"、"my"、"mother"。
2.当把数据拆分出来后(拆分成的数据单位我们称为“词”),就会把这些词建立索引,ElasticSearch内部有一个索引表,用于建立词与数据的对应,结构类似如下(真实格式还会有词的频率、数据长度等信息),索引表存储了词和词所在记录的ID集合,所以可以通过某个词来快速搜索出相关的记录,比如搜索"I",那么会返回1和2,然后可以快速根据ID来获取对应的数据。【请注意,下图只是方便理解,并不是真实的格式】
3.然后我们搜索的时候,分词器也先把我们输入的内容处理(为了与索引表的词统一),然后再从索引表中查找,返回对应的数据记录集合。
例如我输入mother,mother会先转成mom,然后从索引表中找到mom,返回包含mom的记录的ID,然后根据ID获取对应数据,也就是“I like my mom”
搜索引擎选择
Lucene也是一种搜索引擎,为什么不直接使用Lucene?
ElasticSearch实际上底层使用的就是Lucene,虽然Lucene也有很多功能,但Lucene的使用难度较大(也正是使用难度高所以ElasticSearch才对Lucene进行封装),而且ElasticSearc的高级功能也很强大,ES支持了多样的数据分析。除了基本的功能,集群能力也是一个问题,Lucene一开始没有考虑集群,所以对于存储在不同服务器上的大量数据的交互比较麻烦,而ElasticeSearch一开始就是集群思想的,数据存储以一个ElasticSearch节点为单位,多个节点的数据可以交流。
由于底层是Lucene,所以,对于一些elasticsearch底层的东西,有时候你完全可以参照Lucene,比如索引词文件的存储等。为什么不是Solr?
Solr也是一个知名的搜索引擎,它与ElasticSearch各有好处,Solr适用于一些非实时搜索系统(新增的数据不要求马上查出来的),而ElasticSearch适用于一些实时搜索要求较高的系统(电商平台等要求新商品马上可查的系统)。因为Solr在建立索引时,搜索效率下降,实时索引搜索效率不高,而ElasticSearch建立索引的速度较快。ElasticSearch有一个非常显著的特性"NRT":NRT全称Near Real Time,近实时,意思是你插入的数据几乎可以“马上”就可以被搜索出来。这也是为什么它能使用在实时更新要求高的场景的原因。
搜索的处理
上面提了词的拆分,这里提一些关于底层的搜索处理的内容。介绍一下ElasticSearch另一个协助搜索的关键组件--分词器。ElasticSearch的全文搜索离不开分词器的帮助。
分词器通常由分解器tokenizer和词元过滤器token filter组成。
分词器对数据的分词处理:为了提高索引的效率,ElasticSearch会数据进行处理,处理方式主要有字符过滤、词转换、词拆分
字符过滤:过滤一些特殊字符,例如&
、||
、html标签,因为这些词通常搜索意义不大。词转换:把一些意义相同的词统一转成一个词,(同词义转换)比如mom,mother统一转成mom;(大小写转换)he,He统一归为He;还处理一些词意义不大的词(停用词清除),比如英文的“the”,“to”,这些词使用频率很高,但没有具体意义。
词拆分:进行数据的拆分,拆分成词,比如把
good morning,mom
拆分成good
,morining
,mom
。另外,词拆分并不完全是按照数据的最小单位分解的,某一些分词器会把一些词进行组合,因为一些词的组合起来才有索引的意义,比如中文的一些词通常要组合起来才有意义,比如“大”和“家”要组成“大家”才有比较具体的意义,这是为了确保索引词的最小单位是有意义的(比如英文mom的最小单位是m,o,m,内部的分词器要能够区分出mom整个是有意义的才可以确保是采用mom作为索引,而不是采用m和o,也正是因为这个问题,所以英文分词器不能用于中文分词器)。【分词器有很多个,默认的分词器是不能适当对中文数据分词的,它只能把一个个数据按最小的单位拆分,因为英文分词器不能分清楚怎么把词拆分才有意义,由于配置分词器是一个较为靠后的知识点,所以前期将以英文数据为测试数据。】分词文件的存储:
分词文件一般包括三种文件:词典文件,频率文件,位置文件。
词典文件保存了关键词(索引词),还保留了指向频率文件和位置文件的指针。
频率文件记录了词出现的频率。
位置文件记录了这些词出现在哪些数据中。
补充:
- 数据库不是被替代,而是被补充。有时候会将数据同时存储到数据库和ElasticSearch中,在单个查看的时候可以从数据库中查询,在搜索的时候从ElasticSearch中查询;也有的项目由于数据比较简单完全使用elasticsearch来存储数据。
- ElasticSearch是分布式的,但我们是不需要对其集群进行部署的,它自动进行了集群部署和节点发现等功能,我们只需进行很少的配置就能管理集群。在比较靠后的内容才会讲到如何深入管理集群。
小节总结:
- 1.本小节简单讲述了ElasticSearch是什么
- 2.传统搜索的不足
- 3.使用ElasticSearch搜索的好处
- 4.全文搜索和倒排索引
- 5.与其他搜索引擎的比较
- 6.ElasticSearch对于索引词的处理(这个内容是提前讲的内容,是为了帮助了解倒排索引如何建立索引)
基本学习环境搭建
如何操作ElasticSearch
首先要说的是,ElasticSearch是一款软件,有点类似MySQL,我们要操作它的时候,也要给它发送它能识别的命令,而ElasticSearch是面向restful(不知道restful的自查吧)的,所以我们发送的命令是有点类似发送http请求的。
mysql是3306端口,而elasticsearch支持9200和9300端口操作,其中9200面向http,9300面向tcp。9200能够使用普通的http请求来操作elasticsearch,9300需要连接elasticsearch之后再执行命令。
- 对于9200,因为面向http,所以我们可以使用postman发http请求来操作elasticsearch。
- 对于9300,因为面向tcp,我们通常使用一些elasticsearch管理工具(如kibana)进行连接elasticsearch之后再执行命令。(类似navicat之于mysql)
下载、安装和运行(Based Windows)
我们首先来搭建好学习环境,主要是ElasticSearch和Kibana。【请注意,Elasticsearch依赖Java环境】
【Kibana是可选的,下面会介绍一下基于postman的对ElasticSearch操作。】,Kibana是一款对ElasticSearch进行管理的软件,我们可以在Kibana上执行ElasticSearch的命令。
下载:
- ElasticSearch下载:ElasticSearch下载【这里以6.2的为例】
- Kibana下载:Kibana下载 【两个下载都是同一个位置,这里下载以6.2的为例】【Kibana的版本尽量与ElasticSearch的一致,有些版本会连接错误】
安装:
- 两个软件都是不需要安装的,下载后,直接解压即可。
运行:
- 对于ElasticSearch,可以直接在
elasticsearch-6.2.0\bin
中运行elasticsearch.bat
,当提示“started”时,表示运行成功。 - 对于Kibana,可以直接在
kibana-6.2.0-windows-x86_64\bin
中运行kibana.bat
,当提示“Server running at http://localhost:5601”时,表示运行成功。【要先运行ElasticSearch再运行Kibana,因为它要与ElasticSearch进行连接】
如何操作ES
ElasticSearch默认的TCP服务端口是9300,Kibana的服务端口是5601,当我们启动了Kibana之后,它会默认帮我们连接上9300,所以我们可以从http://localhost:5601
中进入Kibana的管理界面来管理ElasticSearch。
如果你是第一次使用,那么ElasticSearch会自动创建一个名为elasticsearch
的集群,Kibana会在这个节点中初始化一个index
我们在Kibana的DevTools中执行一些命令来看一下ElasticSearch。【从http://localhost:5601
中进入】
在输入命令GET /_cat/health?v
后,点击该行右侧的执行按钮。【GET /_cat/health?v
是查看集群的健康状态的命令】
然后就可以在右侧的结果窗口中查看命令执行结果。
【你现在大概都是看不懂命令的意义和结果的意义的了,不过你应该知道哪里输入命令和哪里看执行结果了】
基于postman操作
postman是一个用来发请求的软件,可以使用restful风格的请求来操作elasticsearch。
比如上面的查看集群的命令:GET /_cat/health?v
转成基于restful的是:http://localhost:9200/_cat/health?v
即IP:9200+命令
,其中9200是用于接收restful请求的es监听端口。
补充:
上面的第一次使用并没有涉及到具体的知识,只是让你熟悉一下如何使用Kibana来操作ElasticSearch。下面讲到具体知识点才会具体使用。
小节总结
- 1.讲了ES如何提供服务:9200,9300
- 2.讲了如何下载、安装、运行ElasticSearch和Kibana
- 3.讲述了如何在Kibana中操作ElasticSearch
- 4.讲述了如何在postman中操作ElasticSearch
需要了解的概念
分布式模型相关
- 集群Cluster:所谓集群,就是多个服务节点的集合,集群意味着这些节点是能够相互交流的,不然无法进行数据交互。集群的默认名称是"elasticsearch",多个提供服务的节点会根据集群名来自动加入集群。
- 节点Node:节点是集群的一部分,是集群的最小单元,是可以提供服务的节点。
- 分片shard:分片位于节点上,分片是elasticsearch数据存储的单元,elasticsearch中的数据会存储在分片中。分片可以存储在任意一个节点上。分片分为主分片Primary Shard和副本分片Replica Shard。
- 主分片Primary Shard:当存储一个文档document的时候,会先存储到主分片中,然后再复制到其他的副本分片Replica Shard中。
- 副本分片Replica Shard:副本分片是主分片的复制(备份)。默认情况下,主分片有一个副本分片,主分片不能修改,但副本分片可以后续再增加。
数据存储相关
数据存储在shard中,shard中的数据是以文档document为单位的。document存储在index和type划分的逻辑空间中。document以json为格式,每一个key-value中key可以称为域Field。
- 索引Index:索引是存储具有相同结构的document的集合,意义上有点类似关系型数据库中的数据库,用于存储一系列数据,比如可以说“商品”索引,一般都是个大类,小逻辑划分由Type处理。
- 类型Type:类型是索引的逻辑分区,意义有点类似关系型数据库中的数据表。用来划分索引下不同子类型的数据,比如商品(索引)可以有电子产品(类型),药品(类型)。在同一个分类下的数据一般都具有同种特征,用来定义数据的字段的数量一般也是相同的。每一个document都有一个type和一个id,在存储文档的时候需要指定索引、类型和ID。
- 文档Document:类似于关系型数据库中的记录,是ElasticSearch的数据存储的基本单位,格式与JSON相同。例如:
{
"book_id": 1,
"book_name": "Java Core ",
"book_desc": "A good book, you know!",
"category_id": "1",
"category_name": "Computer"
}
- 域Field:类似于关系型数据库中的字段。
- elasticsearch是面向restful的,下面是restful请求与elasticsearch操作的对应:
请求方法 | 对应操作 | 说明 |
---|---|---|
GET | 读取 | 获取数据 |
POST | 新增 | 新增数据 |
PUT | 修改 | 修改数据或增加数据 |
DELETE | 删除 | 删除数据 |
- 索引用来存储数据,分片也是用来存储数据,它们是怎么对应的?一个索引存储在多个分片上,默认情况下,一个索引有五个主分片,五个副本分片。主分片的数量一旦定下来就不能再修改,但副本分片的数量还可以修改。
小节总结
- 讲了一下ElasticSearch的集群概念,节点是集群的基础服务单位,节点可以提供数据读写服务,数据按分片来存储,主分片是主要数据,可以读取和修改数据,副本分片不支持修改数据。
- 主分片和副本分片的互斥性(为了保证数据不同时丢失)
- elasticsearch的数据的逻辑存储结构(索引->类型->文档)。索引是数据的大分类,类型是数据的小分类。
- 文档的格式
- 索引与分片的关系。一个索引存储在多个分片上
Hello ElasticSearch
前面提了一下index,type,document,说了ElasticSearch的逻辑存储空间。
下面以两个实例:“写document->读document”和“写document->搜索document“来初步演示一下如何存储数据和获取数据。
写->读
如果我们要向ElasticSearch中写入一份数据(document),命令的语法应该如下:
PUT /index名称/type名称/document的ID
{
document的数据
}
上面的语法的意思就是向一个index的一个type中插入一个document,document用id作为标识,后面我们取document的数据也将以这个id为依据。其中index,type是可以不需要我们预创建的,在我们还不会如何创建index和type的时候,你可以先随便打个名字(如果ElasticSearch检测到我们输入的index和type是不存在的,那么它就会以默认的规则帮我们创建出来)。
请在kibana的devtool中执行以下命令来存储一份document:
PUT /douban/book/1
{
"book_id":1,
"book_name":"A Clockwork Orange",
"author":"Anthony Burgess",
"summary":"Fully restored edition of Anthony Burgess' original text of A Clockwork Orange, with a glossary of the teen slang 'Nadsat', explanatory notes, pages from the original typescript, interviews, articles and reviews Edited by Andrew Biswell With a Foreword by Martin Amis 'It is a horrorshow story ...' Fifteen-year-old Alex likes lashings of ultraviolence. He and his gang of friends rob, kill and rape their way through a nightmarish future, until the State puts a stop to his riotous excesses. But what will his re-education mean? A dystopian horror, a black comedy, an exploration of choice, A Clockwork Orange is also a work of exuberant invention which created a new language for its characters. This critical edition restores the text of the novel as Anthony Burgess originally wrote it, and includes a glossary of the teen slang 'Nadsat', explanatory notes, pages from the original typescript, interviews, articles and reviews, shedding light on the enduring fascination of the novel's 'sweet and juicy criminality'. Anthony Burgess was born in Manchester in 1917 and educated at Xaverian College and Manchester University. He spent six years in the British Army before becoming a schoolmaster and colonial education officer in Malaya and Brunei. After the success of his Malayan Trilogy, he became a full-time writer in 1959. His books have been published all over the world, and they include The Complete Enderby, Nothing Like the Sun, Napoleon Symphony, Tremor of Intent, Earthly Powers and A Dead Man in Deptford. Anthony Burgess died in London in 1993. Andrew Biswell is the Professor of Modern Literature at Manchester Metropolitan University and the Director of the International Anthony Burgess Foundation. His publications include a biography, The Real Life of Anthony Burgess, which won the Portico Prize in 2006. He is currently editing the letters and short stories of Anthony Burgess.",
"press":"Penguin Classic",
"publication_date":"2000-02-22"
}
如果要获取ES中存储的document,命令的语法应该如下:
GET /index名/type名/id
一样的,请在kibana中执行下述命令来获取我们上面存储的document:
GET /douban/book/1
返回结果:【返回index名称,type名称,id,原始文档等数据】
很明显地,我们获取到了我们刚刚存储进去的数据。
写->搜索
一样的,我们写多一份数据进ES中:
PUT /douban/book/2
{
"book_id":2,
"book_name":"Kubernetes in Action",
"author":"Marko Luksa",
"summary":"Kubernetes in Action teaches you to use Kubernetes to deploy container-based distributed applications. You'll start with an overview of Docker and Kubernetes before building your first Kubernetes cluster. You'll gradually expand your initial application, adding features and deepening your knowledge of Kubernetes architecture and operation. As you navigate this comprehensive guide, you'll explore high-value topics like monitoring, tuning, and scaling.Kubernetes is Greek for \"helmsman,\" your guide through unknown waters. The Kubernetes container orchestration system safely manages the structure and flow of a distributed application, organizing containers and services for maximum efficiency. Kubernetes serves as an operating system for your clusters, eliminating the need to factor the underlying network and server infrastructure into your designs.",
"press":"Manning Publications",
"publish_date":"2017-08-31"
}
下面将演示搜索的功能,搜索的其中一种语法是:
GET /index名/type名/_search
{
"query":{
"match":{
"字段Field名称":"用于搜索的关键字"
}
}
}
那么,根据我们之前存储的数据,如果我们要查询summary字段有Orange的数据的话,命令如下:
GET /douban/book/_search
{
"query": {
"match": {
"summary":"Orange"
}
}
}
小节总结
- 这小节涉及到了数据的插入,读取,搜索,但仅仅是一个Hello ElasticSearch的例子,所以没有讲到插入数据应该有的前置知识。理论上,你只需要记得这个流程即可。后面会补充这个流程中没有提到的内容。
--To Be Continue