ES深入2-搜索原理

  1. 倒排索引
    1. 原理
    2. 样例
    3. 应用
  2. 分词与标准化
    1. 分词
    2. 标准化
    3. 示例
  3. ES分析器(Analyzer)
  4. 参考资料

倒排索引

ES底层基于lucene实现,而lucene全文索引使用到的核心技术就是倒排索引。倒排索引(Inverted Index)是一种广泛应用于全文检索系统中的数据结构,如搜索引擎、数据库等。它的主要目的是为了高效地支持关键词搜索,即通过一个关键词快速找到包含该关键词的所有文档。倒排索引的基本原理是将文档中出现的关键词作为索引项,每个索引项记录了该关键词在哪些文档中出现过,以及在这些文档中的具体位置。

原理

  1. 分词处理:在构建倒排索引前,首先需要对文档进行分词处理,即将文档拆分为单个词汇或短语。这个过程称为分词(Tokenization)。

  2. 创建索引项:对于每个词汇,创建一个索引项,该索引项记录了该词汇所出现的所有文档的标识符(通常是文档ID)以及在文档中的位置信息。

  3. 数据结构:倒排索引通常使用哈希表、字典树、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.”,处理流程可能如下:

  1. 分词:句子被分割成 ["running", "quickly", "in", "the", "park"],同时转换为小写。

  2. 标准化

    • 去除停用词:移除 “in” 和 “the”,剩下 ["running", "quickly", "park"]
    • 词干提取:如果启用了,可能会将 “running” 转换为 “run”,最终得到 ["run", "quickly", "park"]

通过这样的分词和标准化流程,搜索引擎能够有效地索引和检索文档,提供准确的搜索结果。

ES分析器(Analyzer)

Elasticsearch(ES)的分析器(Analyzer)正是基于上文的分词与标准化原理。分析器(Analyzer)是负责文本分析处理的关键组件,主要由以下三个部分组成:

  1. 字符过滤器(Character Filters):
    字符过滤器位于分析流程的起始端,它们在文本被分词之前对原始文本进行处理。字符过滤器可以用来删除或转换不需要的字符,比如HTML标签、XML实体、表情符号等,以便于后续的分词步骤更加准确。一个分析器可以有零个或多个字符过滤器。

  2. 分词器(Tokenizer):
    分词器是分析器的核心,负责将经过字符过滤器处理的文本切分成一个个基本的文本单位,称为词元(tokens)。分词器根据预设的规则或算法来决定在哪里分割文本,不同的分词器适用于不同的语言特性和需求,如标准分词器(Standard Analyzer)、IK分词器(针对中文)等。一个分析器只能包含一个分词器。

  3. 词元过滤器(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

×

喜欢就点赞,疼爱就打赏