Elasticsearch学习笔记——倒排索引
索引的本质
索引的本质,其实是描述了一个事物到另一个事物之间的关联关系,我们可以通过这种关联关系,即索引,方便快速的从一个事物找到另一个事物。
正常来讲,我们通常是以一个事物具备哪些特征来描述一个事物的,比如:博主是一个帅气、阳光、乐观、向上的人。也就是说,我们从博主出发,能找到帅气、阳光、乐观、向上等四个关键词,这其实就是一个正序索引。如下:
博主 ——> 帅气
博主 ——> 阳光
博主 ——> 乐观
博主 ——> 向上
那么什么倒排索引呢?就是把正序索引反过来。
帅气 ——> 博主
阳光 ——> 博主
乐观 ——> 博主
向上 ——> 博主
ES中的倒排索引
先回忆几个基本概念。
文档:通常情况下,我们会把一个具体的目标进行一定的整理,然后以JSON的形式交给ES。比如商品,通常我们会把商品名称,描述,价格,库存等一系列内容整理好,交给ES。那么,对于ES来说,这个具体的目标就是文档,JSON是ES喜欢的文档表现形式。
文档ID:为了便于对文档进行标识,ES会将接收到的文档进行编号,这个编号可以由ES自动生成,也可以由客户端指定。
单词:文档交给ES后,ES会根据设定的规则,对文档进行分析和拆分,文档将会被拆分成一个个单词。换句话说,对于ES来说,分析后的文档就是由单词组成的。
单词ID:和文档一样,ES也会对单词进行标识,标识的方式同样也是对单词进行编号。
有了以上几个概念,我们再来解释倒排索引。
倒排索引,描述了从单词到文档的关联关系。利用倒排索引,可以快速的通过单词找到和该单词关联的文档列表。倒排索引由两部分组成,一个是单词词典,一个是倒排列表。
一个文档由许多的单词组成,我们交给ES的文档的越多,分析拆分后得到的单词就越多,这些单词被整理组织成一个集合,集合中的每个元素记录了单词本身的一些相关信息以及一个指定倒排列表的指针。
通过单词,我们会在倒排列表中找到一个倒排项,该倒排项中,记录了出现过该单词的所有文档ID,以及单词在文档中的位置信息。也就是说,倒排列表,是倒排项的集合。
倒排列表会以文件的形式,具体的存储在磁盘中的某个位置,这个文件,称之为倒排文件。
单词词典的数据结构
当我们通过ES来查询某个关键字时,ES会先从单词词典中找到这个关键字对应的元素,然后,从元素中的指针定位到倒排列表中的某个倒排项,就能从倒排项中,快速知道,所有包含该关键字的文档列表。所以,单词词典采用什么样的数据结构来存储,是关系到查询速度的重要因素之一。
一般来说,单词词典通常的数据结构有两种,一种是哈希+链表,另一种是树。
哈希+链表
哈希+链表这种形式,和JAVA中老的HashMap的数组结构形式是一样的。在创建索引时,会根据单词的哈希值,计算出单词所在位置,然后存放到该位置的链表中。
树
树是另外一种ES经常用在单词词典中的数据结构,通常是B或B+树。这种数据结构,和MySQL数据库的索引是同样的,也是一种查询高效的数据结构。关于数据结构更多的内容,可以关注博主《数据结构与算法分析》系列笔记。
倒排索引的创建——分词器
我们交给ES的是文档,ES回馈给我们的是倒排索引,那么,ES是如何把文档变成倒排索引的呢?一般而言,会经过三个步骤:
预处理。首先,要对文档内容进行一定程序的整理,如过滤掉其中的html标签等,这个过程,称之为预处理。
分词。根据特定规则,将预处理后的内容拆分成一个个单词,这个过程,称之为分词。
标准化。分词后,文档变成了一个单词的集合,但是,在这个集合中,可能存在一些无意义的,错误的,或重复的单词,那么,在标准化阶段,就是要把这些内容处理掉,以避免这些单词进入词典,影响词典的质量。
在分词阶段,起到关键作用的就是分词器,并且,分词阶段只能有一个分词器。你可以使用ES内置的分词器,也可以第三方提供的分词器或者自定义分词器。通常情况下,ES内置的分词器对中文是不友好的,所以,第三方分词器或者自定义分词器,对于中文搜索站点来说,是必须要做的。
我们来认识一下ES内置的几个分词器,以及一些第三方分词器。
ES自带的分词器:
Standard Analyzer:是默认的分词器,会按词进行拆分,并做英文大写到小写的转换,如果是中文,会按照单字拆分。
Simple Analyzer:按照非字母拆分,同样做小写处理。(貌似还不如默认)
Whitespace Analyzer:空白字符拆分。(一个不如一个……)
Stop Analyzer:相比Simple Analyzer,多了对一些停用词的处理,停用词指的是一些无意义的词,如语气助词等。
Keyword Analyzer:不分词,直接作为一个完整单词输出。(这有啥意思?)
Pattern Analyzer:通过正则表达式自定义分割符,默认是\W+,和Simple Analyzer的拆分规则相同。
以上就是ES自带的分词器,我们发现,这些分词器基本上都无法满足业务需要,尤其是包含中文搜索的业务。那么,我们就需要引入一些第三方的分词器来帮助ES完成分词。常见的第三方分词系统如下:
IK:实现中英文单词的切分,可自定义词库,支持热更新分词词典。
jieba:支持分词和词性标注,支持繁体分词,自定义词典,并行分词等。
Hanlp:由一系列模型与算法组成的Java工具包,目标是普及自然语言处理在生产环境中的应用。
THUAC:中文分词和词性标注。
IK是我们经常用的。简单介绍一下如何使用。
下载IK,安装到ES目录下的bin/plugins中。
在elasticsearch.yml中,通过index.analysis.analyzer.default.type属性,设置为ik,即可使用IK分词器。
重启ES。(各节点重复该过程)
也可以通过在mapping中指定某个请求独立的分词模式。
一般情况下,我们使用IK的max_word模式,即会根据词典穷举文档中所有可能的词。另一种smart模式,会做最简的拆分,会漏掉一些我们可以想要的分词。当然了,在使用索引时,即搜索时,我们对用户输入的关键字是可以用smart模式的, 这种模式,可以使匹配到的内容更加准确,更符合用户的搜索目标。
领取专属 10元无门槛券
私享最新 技术干货