Elasticsearch 分词详解(1)

91 阅读3分钟

1. 分词发生的阶段

在 Elasticsearch 中,分词(Text Analysis) 主要发生在两个阶段:

  1. 索引阶段(Index time)

    • 文本被写入时,字段内容会经过分词器处理,生成一系列词项(terms),存储到倒排索引中。
    • 举例:"Elasticsearch is powerful"[elasticsearch, is, powerful]
  2. 查询阶段(Search time)

    • 查询语句(如 match 查询)会对输入文本再次分词,以便和索引中的倒排词项进行匹配。
    • 举例:搜索 "powerful elasticsearch"[powerful, elasticsearch]

注意:索引阶段和查询阶段的分词器可以不同,这样可以实现 写时规范化,读时灵活匹配


2. 分词器的组成

Elasticsearch 的 分词器(Analyzer) 由三个部分组成:

  1. Character Filters(字符过滤器)

    • 在分词前对文本做预处理。
    • 如:html_strip:去掉 HTML 标签,处理<p>Hello World!</p>,输出为Hello World!
    • 如:mapping:替换指定字符(如将 "™" 替换为 "trademark")
    • 如: pattern_replace:正则替换
  2. Tokenizer(分词器)

    • 核心步骤,把字符串切分成单词,将预处理后的文本拆分为词项(Tokens),是分词的核心步骤。每个 Analyzer 必须包含一个 Tokenizer
    • Standard 会按空格、标点切分。
    • whitespace:仅按空格拆分
    • keyword:不拆分,将整个文本作为一个词项
    • ik_max_word(IK 分词器):中文细粒度拆分
    • ik_smart(IK 分词器):中文粗粒度拆分
  3. Token Filters(词元过滤器)

    • 对分出来的词进一步处理。
    • 如:大小写归一化、去停用词、词干化(running → run)。
    • lowercase:转为小写(默认包含在 standard analyzer 中)
    • stop:去除停用词(如 "the"、"的")
    • synonym:同义词替换(如将 "quick" 替换为 "fast")
    • stemmer:词干提取(如将 "running" 还原为 "run")

3. 分词器的分类

常见分词器:

  1. 内置分词器(Built-in Analyzers)

    • standard(默认,支持 Unicode 规则)
    • simple(按非字母切分,全部小写)
    • whitespace(仅按空格切分)
    • keyword(不分词,整体作为一个 term)
  2. 语言分词器(Language Analyzers)

    • englishsmartcn(中文)、ik_max_word / ik_smart(IK 插件)。
  3. 自定义分词器(Custom Analyzer)

    • 用户可以指定 字符过滤器 + 分词器 + 词元过滤器 来定制分词逻辑。

4. 特定场景的自定义分词器案例

场景:搜索商品名称,需要大小写不敏感、去停用词、支持同义词。

PUT my_index
{
  "settings": {
    "analysis": {
      "filter": {
        "my_synonym_filter": {
          "type": "synonym",
          "synonyms": [
            "iphone, apple phone",
            "tv, television"
          ]
        }
      },
      "analyzer": {
        "my_custom_analyzer": {
          "type": "custom",
          "char_filter": ["html_strip"],
          "tokenizer": "standard",
          "filter": ["lowercase", "stop", "my_synonym_filter"]
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "product_name": {
        "type": "text",
        "analyzer": "my_custom_analyzer"
      }
    }
  }
}

测试分词效果:

POST my_index/_analyze
{
  "analyzer": "my_custom_analyzer",
  "text": "Apple Phone is <b>Powerful</b>"
}

结果包含:[apple, phone, powerful]


5. Ngram 自定义分词器案例 (后续单独讲解)

场景:支持模糊搜索(如输入 "iph" 也能匹配 "iphone")。

PUT ngram_index
{
  "settings": {
    "analysis": {
      "tokenizer": {
        "my_ngram_tokenizer": {
          "type": "ngram",
          "min_gram": 2,
          "max_gram": 5,
          "token_chars": ["letter", "digit"]
        }
      },
      "analyzer": {
        "my_ngram_analyzer": {
          "type": "custom",
          "tokenizer": "my_ngram_tokenizer",
          "filter": ["lowercase"]
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "name": {
        "type": "text",
        "analyzer": "my_ngram_analyzer",
        "search_analyzer": "standard"
      }
    }
  }
}

测试分词效果:

POST ngram_index/_analyze
{
  "analyzer": "my_ngram_analyzer",
  "text": "iphone"
}

结果可能包含:[ip, iph, ipho, iphon, ph, pho, phon, phone, ...]


6. 示例 DSL

插入和查询数据示例:

POST ngram_index/_doc
{
  "name": "iphone 15 pro"
}

POST ngram_index/_doc
{
  "name": "samsung galaxy"
}

GET ngram_index/_search
{
  "query": {
    "match": {
      "name": "iph"
    }
  }
}

结果会命中 "iphone 15 pro"


小结

  • 分词器发生在 索引阶段 & 查询阶段
  • 分词器由 字符过滤器 + 分词器 + 词元过滤器组成。
  • 分词器可分为 内置、语言、自定义三类。
  • 自定义分词器可以结合 同义词、停用词、HTML 处理等场景。
  • Ngram 分词器适合 模糊搜索、前缀/部分匹配场景。