ik中文分词器使用

IK分词器介绍

在ElasticSearch中默认使用的分词器为Standard分词器,该分词器对中文不友好,对中文的处理方式是按单个汉字分词,无法识别中文里的词语、短语等语义单元。例如对于 "汉朝" 这个词,默认分词器会将其拆分为 ["汉", "朝"] 两个独立字符,match查询会匹配所有包含 "汉"或"朝" 字符的文档,这意味着不仅会匹配 "汉朝",还会匹配包含 "汉"(如 "汉景帝"、"汉武帝")或 "朝"(如 "唐朝"、"明朝")的任何文档。

IK 分词器(IK Analyzer for Elasticsearch) 正是为解决中文分词痛点而生的开源分词插件,它专为中文文本优化,能精准识别中文词语,是 ES 生态中最主流的中文分词解决方案。

核心分词模式

在IK分词器中,有两种分词模式,分别是ik_smart、ik_max_word,可根据业务场景灵活切换:

  1. ik_smart(智能分词)
    • 特点:采用最少切分策略,会做最粗粒度的拆分
    • 示例:对于 "中华人民共和国国歌",会拆分为 ["中华人民共和国", "国歌"]
    • 适用场景:需要快速分词且希望词语颗粒度较大的场景,如标题检索、简单匹配等
  2. ik_max_word(最大分词)
    • 特点:采用最细粒度切分策略,会穷尽所有可能的词语组合。
    • 示例:对于 "中华人民共和国国歌",会拆分为 ["中华人民共和国", "中华人民", "中华", "华人", "人民共和国", "人民", "人", "民", "共和国", "共和", "国", "国歌"]
    • 适用场景:需要全面细致分词的场景,如全文检索、深度语义分析等,能提高召回率

两种分词器使用的最佳实践是:索引时用ik_max_word,在搜索时用ik_smart。

不使用ik分词器,使用es的默认分词模式:会把这五个字拆分成五个独立的字。

1

使用ik分词器的ik_smart分词模式拆分后

2

使用ik分词器的ik_max_word分词模式拆分后

3

再以“中华人民共和国”这个文本进行举例。这里使用的是POST方式,这也是官方API推荐的方法,虽然使用GET也行,但不符合严格的HTTP规范。

ik_smart

POST _analyze
{
    "analyzer":"ik_smart",
    "text":"中华人民共和国"
}

ik_max_word

POST _analyze
{
    "analyzer":"ik_max_word",
    "text":"中华人民共和国"
}

4

5

工作原理

IK 分词器的分词流程分为 3 个核心步骤:

  1. 字符过滤:去除特殊字符(如标点、空格),统一大小写。
  2. 分词处理:基于词典匹配(正向 / 反向最大匹配算法)拆分文本,优先匹配最长词,再递归拆分剩余部分。
  3. 词过滤:过滤停用词、标点,输出最终分词结果。

应用场景

  1. 中文全文检索:电商商品标题 / 详情搜索、新闻资讯检索、企业文档检索等。
  2. 中文文本分析:用户评论情感分析、关键词提取、内容分类等。
  3. 多语言混合场景:支持中英文混合文本分词(如 “iPhone 17 发布会” → [iPhone, 17, 发布会])。

优缺点

优点 缺点
中文分词精度高,适配语义 词库需定期维护(新增行业词、网络热词)
支持两种分词模式,灵活适配索引 / 搜索 分词速度略低于默认单字分词(但满足绝大多数场景)
自定义词库配置简单,支持远程更新 对生僻词、未登录词(如网络新词)拆分效果依赖词库
社区活跃,更新及时(适配 ES 最新版本) 不支持分词歧义消解(如 “苹果” 既指水果也指品牌)

windows系统安装与配置IK

  1. 下载

官网下载地址:https://github.com/infinilabs/analysis-ik

可用的下载地址:https://release.infinilabs.com/analysis-ik/stable/

注意:下载的版本必须和es的版本保持一致。

6

  1. 解压

在es的plugins文件夹下创建ik文件夹,然后将下载好的压缩包解压到该目录中。

7

验证安装是否生效

对指定文本进行分析并返回文本经过分析器处理后的的详细结果。

当未安装IK分词器时,Elasticsearch 会使用默认分析器(standard 分析器),对于中文文本,标准分析器会将每个汉字拆分为独立的词元。

GET _analyze
{
  "text":"我不喜欢你"
}

例如对于文本 "我不喜欢你",默认分析的结果会将其拆分为以下形式。

{
  "tokens": [
    {"token": "我", "start_offset": 0, "end_offset": 1, "type": "<IDEOGRAPHIC>", "position": 0},
    {"token": "不", "start_offset": 1, "end_offset": 2, "type": "<IDEOGRAPHIC>", "position": 1},
    {"token": "喜", "start_offset": 2, "end_offset": 3, "type": "<IDEOGRAPHIC>", "position": 2},
    {"token": "欢", "start_offset": 3, "end_offset": 4, "type": "<IDEOGRAPHIC>", "position": 3},
    {"token": "你", "start_offset": 4, "end_offset": 5, "type": "<IDEOGRAPHIC>", "position": 4}
  ]
}

1

当已安装IK分词器时,ES查询的时候默认不会自动使用IK,需要在请求中明确指定IK分词器才能生效,如下所示,分别采用两种分词模式进行拆分查询。

GET _analyze
{
  "analyzer":"ik_smart",
  "text":"我不喜欢你"
}

9

GET _analyze
{
  "analyzer":"ik_max_word",
  "text":"我不喜欢你"
}

10

索引配置映射

创建 emperor 索引及文档。

POST /emperor/_doc
{
    "name":"李世民",
    "dynasty":"唐朝",
    "age":51
}

POST /emperor/_doc
{
    "name":"刘邦",
    "dynasty":["秦朝","汉朝"],
    "age":61
}

POST /emperor/_doc
{
    "name":"朱元璋",
    "dynasty":"明朝",
    "age":70
}

POST /emperor/_doc
{
    "name":"乾隆",
    "dynasty":"清朝",
    "age":89
}

下面将使用match匹配汉朝数据,可以看到由于ES采用的是默认Standard分词模式,匹配的数据并不是我们想要的数据。虽然我们已经安装了IK分词器。

GET /emperor/_search
{
  "query": {
    "match": {
      "dynasty": "汉朝"
    }
  }
}

11

如果想要精准匹配,可以使用以下两种方式,这两种方式与安不安装IK分词器没关系,都能实现精准匹配。

方式一

GET /emperor/_search
{
  "query": {
    "match": {
      "dynasty.keyword": "汉朝"
    }
  }
}

12

方式二

GET /emperor/_search
{
  "query": {
    "term": {
      "dynasty.keyword": "汉朝"
    }
  }
}

13

如果我们不想使用keyword,也不想使用term,还是想通过match去实现精准匹配,可以在创建索引的时候配置映射,若索引已存在,则需重建索引。

  1. 创建索引的同时配置映射
#这里只对dynasty做了映射处理,如果其它字段也要处理可以继续添加
PUT /emperor
{
  "mappings": {
    "properties": {
      "dynasty": { 
        "type": "text",
        "analyzer": "ik_smart",  # 使用IK分词器(智能分词,适合精确匹配)
        "search_analyzer": "ik_smart"
      }
    }
  }
}
  1. 若索引已存在,则需要通过重建索引修改映射,因为Elasticsearch 不允许直接修改已存在索引的映射(因为映射定义了数据的存储结构,直接修改可能导致数据不一致)。
#创建新索引(如emperor_new),配置目标映射
PUT /emperor_new
{
  "mappings": {
    "properties": {
      "dynasty": { 
        "type": "text",
        "analyzer": "ik_smart", 
        "search_analyzer": "ik_smart"
      }
    }
  }
}

14

# 使用_reindex API迁移数据
POST /_reindex
{
  "source": {
    "index": "emperor"  // 旧索引名
  },
  "dest": {
    "index": "emperor_new"  // 新索引名
  }
}

15

# 删除旧索引
DELETE /emperor

16

此时通过新创建的新索引使用match查询可以实现精准匹配。

GET /emperor_new/_search
{
  "query": {
    "match": {
      "dynasty": "汉朝"
    }
  }
}

17

但是如果还想要用原来旧的索引名查询,可以执行以下命令去给新索引创建别名,执行之后即可以用新索引查询,也可以用旧索引查询。但要注意实际上只有新索引。

# 为新索引创建别名(保持查询接口不变)
POST /_aliases
{
  "actions": [
    {
      "add": {
        "index": "emperor_new",
        "alias": "emperor" 
      }
    }
  ]
}

18

19

20

posted @ 2025-09-20 12:23  相遇就是有缘  阅读(27)  评论(0)    收藏  举报