一、Elasticsearch入门
1. Elasticsearch简介
- Elasticsearch是什么
Elasticsearch(ES)
是一个基于Lucene
构建的开源、分布式、RESTful
接口的全文搜索引擎。同时,Elasticsearch
还是一个分布式文档数据库,其中每个字段均是被索引的数据且可被搜索,它能够扩展至数以百计的服务器储存以及处理PB级的数据。它可以在很短时间内储存、搜索和分析大量的数据。
- Elasticsearch的优点
- 横向可扩展性:只需要增加一台机器,做一点配置,启动一下
Elasticsearch
进程就可以并入集群。- 分片机制提供更好的分布性:同一个索引分成多个分片(sharding),这点类似于HDFS的块机制;分而治之的方式可以提升处理效率。
- 高可用:提供复制(replica)机制,一个分片可以设置多个复制,使得某台服务器在宕机的情况下,集群仍旧可以照常运行,并会把服务器宕机丢失的数据信息恢复到其他的可用节点上。
- 使用简单:只需一条命令就可以下载文件,然后很快就能搭建一个站内搜索引擎。
2. 全文搜索
全文搜索是指计算机搜索程序通过扫描文章中的每一个词,对每一个词建立一个索引,指明该词在文章中出现的次数和位置,当用户查询时,搜索程序就根据实现建立好的索引进行查找,并将查找结果反馈给用户。这个过程类似于通过字典中的搜索字表查字的过程。Lucene
是目前全球使用最广的全文搜索引擎开源库。
- Lucene介绍
Lucene
是Apache软件基金会4 jakarta项目组的一个子项目,是一个开放源代码的全文检索引擎工具包,但它不是一个完整的全文检索引擎,而是一个全文检索引擎的架构,提供了完整的查询引擎和索引引擎,部分文本分析引擎(英文与德文两种西方语言)。Lucene
的目的是为软件开发人员提供一个简单易用的工具包,以方便的在目标系统中实现全文检索的功能,或者是以此为基础建立起完整的全文检索引擎。
- Lucene倒排索引
倒排索引源于实际应用中需要根据属性的值来查找记录。这种索引表中的每一项都包括一个属性值和具有该属性值的各记录的地址、出现频次等相关信息。由于不是由记录来确定属性值,而是由属性值来确定记录的位置,因而称为倒排索引(inverted index)。带有倒排索引的文件我们称之为倒排索引文件,简称倒排文件(inverted file)。
- Lucene倒排索引原理
假设有两篇文章如下:
文章1的内容为:Tom lives in Guangzhou,I live in Guangzhou too
文章2的内容为:He once lived in Shanghai.
- 取得关键词
全文分析:由于Lucene
是基于关键词索引和查询的,首先我们要取得这两篇文章的关键词,通常我们需要如下处理措施:
- 我们现在有的是文章内容,即一个字符串,我们先要找出字符串中的所有单词,即分词。英文单词由于用空格分隔,比较好处理。中文单词间是连在一起的需要特殊的分词处理。
- 文章中的”in”, “once” “too”等词没有什么实际意义,中文中的“的”“是”等字通常也无具体含义,这些不代表概念的词可以过滤掉。
- 用户通常希望查“He”时能把含“he”,“HE”的文章也找出来,所以所有单词需要统一大小写。
- 用户通常希望查“live”时能把含“lives”,“lived”的文章也找出来,所以需要把“lives”,“lived”还原成“live”。
- 文章中的标点符号通常不表示某种概念,也可以过滤掉。
在Lucene
以上措施由Analyzer经过上面处理后:
文章1的所有关键词为:[tom] [live] [guangzhou] [i] [live] [guangzhou]
文章2的所有关键词为:[he] [live] [shanghai]
- 建立倒排索引
有了关键词后,我们就可以建立倒排索引了。上面的对应关系是:“文章号”对“文章中所有关键词”。倒排索引把这个关系倒过来,变成:“关键词”对“拥有该关键词的所有文章号”。
文章1,2经过倒排后的对应关系如下:
| 关键词 | 文章号 |
| :--------: | :--------: |
|guangzhou | 1 |
| he | 2 |
| i | 1 |
| live | 1,2 |
| shanghai | 2 |
| tom | 1 |
通常仅知道关键词在哪些文章中出现还不够,我们还需要知道关键词在文章中出现次数和出现的位置,通常有两种位置:
- 字符位置,即记录该词是文章中第几个字符(优点是关键词亮显时定位快);
- 关键词位置,即记录该词是文章中第几个关键词(优点是节约索引空间、词组查询快),
Lucene
中记录的就是这种位置。
加上“出现频率”和“出现位置”信息后,我们的索引结构变为:
| 关键词 | 文章号[出现频率] | 出现位置 |
| :--------: | :--------:| :------: |
| guangzhou | 1[2] | 3,6 |
| he | 2[1] | 1 |
| i | 1[1] | 4 |
| live | 1[2] / 2[1] | 2,5 / 2 |
| shanghai | 2[1] | 3 |
| tom | 1[1] | 1 |
以live这行为例我们说明一下该结构:live在文章1中出现了2次,文章2中出现了一次,它的出现位置为“2,5,2”这表示什么呢?我们需要结合文章号和出现频率来分析,文章1中出现了2次,那么“2,5”就表示live在文章1的关键词中出现的两个位置,文章2中出现了1次,剩下的“2”就表示live是文章2的关键词中第2个关键字。
以上就是Lucene
索引结构中最核心的部分。我们注意到关键字是按字符顺序排列的(Lucene
没有使用B树结构),因此Lucene
可以用二元搜索算法(或叫二分查找/折半查找)快速定位关键词。
3. 基础知识
- Elasticsearch术语及概念
1. 索引词(term)
在Elasticsearch
中索引词(term)是一个能够被索引的精确值。foo、Foo、FOO是不同的索引词。索引词(term)是可以通过term查询进行准确的搜索。
2. 文本(text)
文本是一段普通的非结构化文字。通常,文本会被分析成一个个的索引词,储存在Elasticsearch
的索引库中。为了让文本能够进行搜索,文本字段需要事先进行分析;当对文本中的关键词进行查询的时候,搜索引擎应该根据条件搜索出原文本。
3. 分析(anslysis)
分析是将文本转换为索引词的过程,分析的结果依赖于分词器。比如:FOO BAR、Foo-Bar、foo bar这几个单词有可能会被分析成相同的索引词foo和bar,这些索引词存储在Elasticsearch
的索引库中。当FoO:bAR进行全文搜索的时候,搜索引擎根据匹配计算也能在索引库中搜索出之前的内容。这就是Elasticsearch
的搜索分析。
4. 集群(cluster)
集群有一个或多个结点组成,对外提供服务,对外提供索引和搜索功能。在所有结点,一个集群有一个唯一的名称默认为Elasticsearch。当某个节点被设置为相同的集群名时,就会自动加入集群。当需要有多个集群的时候,必须确保每个集群的名称不能重复。
每个集群都有一个主节点是集群自动选择产生,并且可以决定如果当前主节点失败,哪些可以替换。
5. 节点(node)
节点是属于Elasticsearch
群集的运行实例。测试的时候,在一台服务器可以启动多个节点,但通常情况下应该在一台服务器运行一个节点。在启动时,节点将使用单播(或组播,但是必须指定)来发现使用相同的群集名称的群集,并会尝试加入该群集。
6. 路由(routing)
当存储一个文档时,它会存储在一个主分片里。这分片的选择是通过哈希的路由值。默认情况下,路由值来自文档的ID;如果该文档指定了父文档,则使用父文档的ID(以确保这个子文档和父文件都存储在相同的分片上)。这个路由值可以在索引的时候,通过指定数值或者配置字段映射来覆盖。
7. 分片(shard)
一个分片是一个单一的Lucene
的实例。这是一个低级别的通过Elasticsearch
自动管理的“工作者”单元。索引是一个逻辑命名空间指向主分片和副本分片。索引的主分片和副本分片的数量需要明确的指定。然而你的代码应该只处理一个索引。Elasticsearch
分配集群中所有节点的分片。在节点出现故障或增加新节点的时候,可以自动的将一个节点上的分片移动到另一个节点上。
8. 主分片(primary shard)
每个文档都存储在一个主要分片上。当你索引一个文档时,索引首先生成在主分片上,然后才到主分片的所有副本上。默认情况下,索引有5个主分片。可以指定更多或更少的主分片来适应索引可以处理的文档数。一旦创建了索引,就不能改变索引中主分片的数量。
9. 副本分片(replica shard)
每个主分片可以有零个或多个副本。副本是主分片的一个拷贝,有两个作用:
- 故障转移:如果主分片有问题,副本分片可以提升为主分片;
- 提高性能:获取和搜索请求可以处理主分片或副本分片。
默认情况下,每个主分片有一个副本,不过索引的副本数量可以动态地改变。在同一个节点上,一个副本分片将永远不会和其主分片一起运行。10. 复制(replica)
Elasticsearch
允许创建一个或多个拷贝,索引分片就形成了所谓的副本或副本分片。复制的重要性在于:
- 它提供了高可用性,当节点失败的时候不受影响。需要注意的是,一个复制的分片不会储存在同一节点中。
- 它允许你扩展搜索量,提高并发量,因为搜索可以在所有副本上并行执行。
11. 索引(index)
索引就是像关系数据库中的“数据库”。通过映射可以定义成多种类型。索引是一个逻辑命名空间映射到一个或多个主要的分片,可以有零个或多个副本分片。
12. 类型(type)
Type是相当于关系数据库中的“表”。每种类型都有一列字段,用来定义文档的类型。映射定义了对在文档中的每个字段如何进行分析。
13. 文档(document)
文档是存储在Elasticsearch
中的一个JSON文件。这是相当与关系数据库中表的一行数据。每个文档被存储在索引中,并具有一个类型和一个id。一个文档是一个JSON对象(也被称为在其他语言中的 hash / hashmap / associative array(关联数组)),其中包含零个或多个字段 或者 键值对。原始JSON文档将被存储在索引的_source字段,在获得(getting)或者 搜索(searching)默认的返回时,得到或搜索文档。
14. 映射(mapping)
映射是像关系数据库中的”模式定义“。每个索引都有一个映射,它定义了每个索引的类型,再加上一些索引范围的设置。映射可以被明确地定义,或者在一个文档被索引的时候自动生成。
15. 字段(field)
文档中包含的一组字段或键值对。字段的值可以是一个简单的(标量)值(如字符串,整数,日期),或者一个嵌套的结构就像一个数组或对象。一个字段就是类似关系数据库表中的一列。映射的每个字段有一个字段的类型“type”(不要与文档类型混淆),表示那种类型的数据可以存储在该字段里,如:整数,字符串,对象。映射还允许你定义(除其他事项外)一个字段的值如何进行分析。
16. 来源字段(source field)
默认情况下,你的JSON文档将被索引存储在_source字段里面,所有的get(获取)和search(搜索)请求将返回的该字段。这将允许你直接从搜索结果中访问到源数据,而不需要再次发起请求检索。
注:索引将返回完整的的JSON字符串给你,即使它包含无效的JSON。此字段里的内容不表示任何该对象里面的数据如何被索引。
17. 主键(ID)
每个文档ID标识了一个文档。一个文档的索引/类型/ ID必须是唯一的。如果没有提供ID,将是自动生成。