Elasticsearch倒排索引结构

本文详细介绍了倒排索引的概念及其在Elasticsearch中的应用,通过将数据字段建立倒排索引,实现快速搜索。倒排索引包括Term Dictionary、Term Index和Posting List,允许通过关键词迅速定位到文档。这种索引结构极大地提高了全文检索的效率。

一切设计都是为了提高搜索的性能

倒排索引(Inverted Index)也叫反向索引,有反向索引必有正向索引。通俗地来讲,正向索引是通过key找value,反向索引则是通过value找key。

先来回忆一下我们是怎么插入一条索引记录的:

复制代码

curl -X PUT "localhost:9200/user/_doc/1" -H 'Content-Type: application/json' -d'
{
    "name" : "Jack",
    "gender" : 1,
    "age" : 20
}
'

复制代码

其实就是直接PUT一个JSON的对象,这个对象有多个字段,在插入这些数据到索引的同时,Elasticsearch还为这些字段建立索引——倒排索引,因为Elasticsearch最核心功能是搜索。

那么,倒排索引是个什么样子呢?

首先,来搞清楚几个概念,为此,举个例子:

假设有个user索引,它有四个字段:分别是name,gender,age,address。画出来的话,大概是下面这个样子,跟关系型数据库一样

Term(单词):一段文本经过分析器分析以后就会输出一串单词,这一个一个的就叫做Term(直译为:单词)

Term Dictionary(单词字典):顾名思义,它里面维护的是Term,可以理解为Term的集合

Term Index(单词索引):为了更快的找到某个单词,我们为单词建立索引

Posting List(倒排列表):倒排列表记录了出现过某个单词的所有文档的文档列表及单词在该文档中出现的位置信息,每条记录称为一个倒排项(Posting)。根据倒排列表,即可获知哪些文档包含某个单词。(PS:实际的倒排列表中并不只是存了文档ID这么简单,还有一些其它的信息,比如:词频(Term出现的次数)、偏移量(offset)等,可以想象成是Python中的元组,或者Java中的对象)

(PS:如果类比现代汉语词典的话,那么Term就相当于词语,Term Dictionary相当于汉语词典本身,Term Index相当于词典的目录索引)

我们知道,每个文档都有一个ID,如果插入的时候没有指定的话,Elasticsearch会自动生成一个,因此ID字段就不多说了

上面的例子,Elasticsearch建立的索引大致如下:

name字段:

age字段:

gender字段:

address字段:

Elasticsearch分别为每个字段都建立了一个倒排索引。比如,在上面“张三”、“北京市”、22 这些都是Term,而[1,3]就是Posting List。Posting list就是一个数组,存储了所有符合某个Term的文档ID。

只要知道文档ID,就能快速找到文档。可是,要怎样通过我们给定的关键词快速找到这个Term呢?

当然是建索引了,为Terms建立索引,最好的就是B-Tree索引(PS:MySQL就是B树索引最好的例子)。

首先,让我们来回忆一下MyISAM存储引擎中的索引是什么样的:

我们查找Term的过程跟在MyISAM中记录ID的过程大致是一样的

MyISAM中,索引和数据是分开,通过索引可以找到记录的地址,进而可以找到这条记录

在倒排索引中,通过Term索引可以找到Term在Term Dictionary中的位置,进而找到Posting List,有了倒排列表就可以根据ID找到文档了

(PS:可以这样理解,类比MyISAM的话,Term Index相当于索引文件,Term Dictionary相当于数据文件)

(PS:其实,前面我们分了三步,我们可以把Term Index和Term Dictionary看成一步,就是找Term。因此,可以这样理解倒排索引:通过单词找到对应的倒排列表,根据倒排列表中的倒排项进而可以找到文档记录)

为了更进一步理解,下面从网上摘了两张图来具现化这一过程:

 

根据单一职责原则,一篇只讲一件事情,关于倒排索引结构就讲到这里,至于更多细节,比如:压缩,存储那些以后再説

 

### Elasticsearch倒排索引的数据结构详解 #### 1. 基本概念 倒排索引是一种用于加速全文检索的技术,它是 Elasticsearch 的核心组件之一。通过构建倒排索引Elasticsearch 可以高效地处理大规模数据集上的查询操作[^1]。 #### 2. 数据结构组成 倒排索引由两部分构成:词项列表(Term List)和文档列表(Document List)。 - **词项列表**:包含了所有可能的关键词及其对应的元信息。这些关键词通常是通过对文档内容进行分词得到的结果。 - **文档列表**:对于每一个关键词,记录了包含该关键词的所有文档 ID 和其他相关信息(如频率、位置等)[^4]。 #### 3. 实际案例解析 假设存在如下三个文档: - 文档 1:“Elasticsearch is a powerful search engine” - 文档 2:“Elasticsearch uses inverted index” - 文档 3:“Search engines use indexes” 经过分词后,可以生成一个简单的倒排索引表: | Term | Document IDs | |--------------|-------------| | elasticsearch| 1, 2 | | is | 1 | | a | 1 | | powerful | 1 | | search | 1, 3 | | engine | 1, 3 | | uses | 2, 3 | | inverted | 2 | | index | 2, 3 | 在这个表格中,“Term” 列表示所有的唯一词语,而 “Document IDs” 表示哪些文档包含这个词语。例如,术语 “elasticsearch” 出现在文档 1 和文档 2 中[^3]。 #### 4. 高级特性 除了基本的文档映射外,倒排索引还可以存储更多细节来支持复杂的查询需求。例如: - **词频 (TF)**:某个词在一个特定文档中出现的次数。 - **文档长度**:用来计算权重的一部分。 - **位置信息**:某些场景下需要知道词语在原文中的确切位置以便执行短语匹配或其他高级功能。 以下是创建倒排索引的一个简化 Python 示例代码片段展示如何手动模拟这一过程: ```python from collections import defaultdict def build_inverted_index(documents): inverted_index = defaultdict(list) for doc_id, text in enumerate(documents, start=1): terms = text.lower().split() for term in set(terms): # Use unique terms per document if doc_id not in inverted_index[term]: inverted_index[term].append(doc_id) return dict(inverted_index) documents = [ "Elasticsearch is a powerful search engine", "Elasticsearch uses inverted index", "Search engines use indexes" ] inverted_index = build_inverted_index(documents) print(inverted_index) ``` 运行上述脚本会输出类似于下面这样的结果: ```plaintext { 'elasticsearch': [1, 2], 'is': [1], 'a': [1], 'powerful': [1], 'search': [1, 3], 'engine': [1, 3], 'uses': [2, 3], 'inverted': [2], 'index': [2, 3] } ``` 此代码仅作为教学用途,并未考虑实际应用中的诸多优化措施以及复杂情况下的性能考量。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值