倒排索引
ES底层基于lucene实现,而lucene全文索引使用到的核心技术就是倒排索引。倒排索引(Inverted Index)是一种广泛应用于全文检索系统中的数据结构,如搜索引擎、数据库等。它的主要目的是为了高效地支持关键词搜索,即通过一个关键词快速找到包含该关键词的所有文档。倒排索引的基本原理是将文档中出现的关键词作为索引项,每个索引项记录了该关键词在哪些文档中出现过,以及在这些文档中的具体位置。
原理
分词处理:在构建倒排索引前,首先需要对文档进行分词处理,即将文档拆分为单个词汇或短语。这个过程称为分词(Tokenization)。
创建索引项:对于每个词汇,创建一个索引项,该索引项记录了该词汇所出现的所有文档的标识符(通常是文档ID)以及在文档中的位置信息。
数据结构:倒排索引通常使用哈希表、字典树、B树等高效数据结构来存储索引项,以便快速查询。每个关键词对应一个列表或集合,其中包含该词出现的所有文档ID。
样例
假设我们有两个文档:
- 文档1(ID=1):“The quick brown fox jumps over the lazy dog.”
- 文档2(ID=2):“A quick brown dog jumps over the fence.”
经过分词处理,我们得到以下词汇集合:
- “the”, “quick”, “brown”, “fox”, “jumps”, “over”, “lazy”, “dog”, “a”, “fence”
接下来,构建倒排索引:
- “the”: [1, 2]
- “quick”: [1, 2]
- “brown”: [1, 2]
- “fox”: [1]
- “jumps”: [1, 2]
- “over”: [1, 2]
- “lazy”: [1]
- “dog”: [1, 2]
- “a”: [2]
- “fence”: [2]
在这个例子中,每个关键词都指向一个文档ID列表,表明了该词出现在哪些文档中。例如,关键词”quick”对应的列表是[1, 2],意味着”quick”出现在文档1和文档2中。
应用
当用户输入查询关键词时,搜索引擎只需直接在倒排索引中查找该关键词,即可立即获取包含该关键词的所有文档ID,从而大大加快了搜索的速度。此外,通过进一步分析这些文档ID集合(如计算交集、并集),搜索引擎还能支持更复杂的查询需求,如布尔查询、短语查询等。
分词与标准化
分词
分词(Tokenization)是将文本数据切分成更小的有意义单位(称为tokens或词元)的过程,这对于全文搜索至关重要。标准化(Normalization)则是将这些词元转换为标准形式,以提高搜索的一致性和准确性。
- 比如:可以按照空格分割,将 “the quick brown fox jumps” 切分为[“the”, “quick”, “brown”, “fox”, “jumps”];
- 也可以按照语言的词汇语法分割,将 “一只白色的狐狸跳进草丛” 切分为[“一”, “只”, “白色”, “的”, “狐狸”, “跳进”, “草丛”]
标准化
标准化是将分词后的词元转换成统一的格式,以便于比较和匹配。常见的标准化操作包括:
小写转换:将所有词元转换为小写,确保搜索时大小写不敏感。比如:”Fox”转换为”fox”;
词干提取:通过去除词缀(如复数形式、时态变化等),将词元还原为其词根形式,有助于匹配变体形式的词汇。比如:”foxes” 转换为 “fox”;
去除停用词:从词元流中移除常见但无实际意义的词汇,如“is”、“the”等,以减少噪音并提高搜索效率;
同义词处理:将同义词或近义词映射到同一个标准化的词形,增强查询的召回率。
示例
假设我们有一个句子:“Running quickly in the park.”,处理流程可能如下:
分词:句子被分割成
["running", "quickly", "in", "the", "park"]
,同时转换为小写。标准化:
- 去除停用词:移除 “in” 和 “the”,剩下
["running", "quickly", "park"]
。 - 词干提取:如果启用了,可能会将 “running” 转换为 “run”,最终得到
["run", "quickly", "park"]
。
- 去除停用词:移除 “in” 和 “the”,剩下
通过这样的分词和标准化流程,搜索引擎能够有效地索引和检索文档,提供准确的搜索结果。
ES分析器(Analyzer)
Elasticsearch(ES)的分析器(Analyzer)正是基于上文的分词与标准化原理。分析器(Analyzer)是负责文本分析处理的关键组件,主要由以下三个部分组成:
字符过滤器(Character Filters):
字符过滤器位于分析流程的起始端,它们在文本被分词之前对原始文本进行处理。字符过滤器可以用来删除或转换不需要的字符,比如HTML标签、XML实体、表情符号等,以便于后续的分词步骤更加准确。一个分析器可以有零个或多个字符过滤器。分词器(Tokenizer):
分词器是分析器的核心,负责将经过字符过滤器处理的文本切分成一个个基本的文本单位,称为词元(tokens)。分词器根据预设的规则或算法来决定在哪里分割文本,不同的分词器适用于不同的语言特性和需求,如标准分词器(Standard Analyzer)、IK分词器(针对中文)等。一个分析器只能包含一个分词器。词元过滤器(Token Filters):
词元过滤器在分词之后运行,对生成的词元序列进行进一步的加工。它们可以执行诸如转换词元大小写、去除停用词、词干提取(如将“running”变为“run”)、同义词替换等多种操作,以优化索引过程或提升搜索结果的相关性。
这三个组成部分共同作用,使Elasticsearch能够高效地处理和索引文本数据,同时也支持用户根据具体需求自定义分析器,以适应不同的搜索场景和语言特性。
复杂样例:
PUT test-index
{
"settings": {
"analysis": {
"analyzer": {
"my_custom_analyzer": {
"type": "custom",
"char_filter": [
"html_strip",
"my_mappings_char_filter"
],
"tokenizer": "standard"
}
},
"char_filter": {
"my_mappings_char_filter":
{
"type": "mapping",
"mappings": [
"٠ => 0",
"١ => 1",
"٢ => 2",
"٣ => 3",
"٤ => 4",
"٥ => 5",
"٦ => 6",
"٧ => 7",
"٨ => 8",
"٩ => 9"
]
}
}
}
},
"mappings": {
"properties": {
"my_text": {
"type": "text",
"analyzer": "my_custom_analyzer"
}
}
}
}
POST test-index/_analyze
{
"analyzer": "my_custom_analyzer",
"text": "<p>My phone number is <b>١٢٥٠١٥</b> </p>"
}
参考资料
- 通义千问
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 duval1024@gmail.com