IK分词词典热更新

更新时间:
复制 MD 格式

Lindorm 搜索引擎使用的 IK 分词器支持热更新主词典和停用词词典。本文以 testAnalyzer 索引为例,演示两类词典的更新与验证过程。

方案概述

主词典决定哪些词被识别为完整词语,停用词词典决定哪些词在写入和查询时会被排除,两者均在上传自定义词典文件后由服务端重新构建生效。按需求选择更新对象:

更新对象

需求

主词典

默认分词结果无法满足需求时,则需要将预期分词结果加入自定义主词典

停用词词典

屏蔽“吗”“的”“啊”等无检索意义的词,避免其参与查询并影响查询结果

重要

词典更新完成后,历史数据需要重新写入,服务端才能使用更新后的词典对数据重新分词并构建索引。

前提条件

  • 已创建 Lindorm 实例并开通搜索引擎,详情可参见开通指南。

  • 已将客户端的IP地址加入到Lindorm实例的白名单中。具体操作,请参见设置白名单。

更新主词典

示例环境

以下示例创建 testAnalyzer 索引,并写入 3 条数据。

PUT testAnalyzer
{
  "mappings": {
    "properties": {
      "description": {
        "type": "text",
        "analyzer": "ik_max_word",
        "search_analyzer": "ik_smart"
      }
    }
  }
}
POST testAnalyzer/_bulk?refresh
{ "index": {"_id": "1"} }
{ "description": "ik支持词典热更新吗" }
{ "index": {"_id": "2"} }
{ "description": "今天天气热吗" }
{ "index": {"_id": "3"} }
{ "description": "我有一本词典" }

问题复现

使用 Analyzer API 查看“词典热更新”的分词结果。

GET _analyze
{
  "text": "词典热更新",
  "analyzer": "ik_smart"
}

此时,“词典热更新”没有作为一个完整的词被识别。

使用“词典热更新”作为查询条件查询 testAnalyzer 索引。

GET testAnalyzer/_search
{
  "query": {
    "match": {
      "description": {
        "query": "词典热更新",
        "analyzer": "ik_smart"
      }
    }
  }
}

上述 3 条记录都会返回。原因是查询时,“词典热更新”被切分为“词典”“热”和“更新”3 个条件,只要任意条件与数据匹配,对应数据就会返回。如果希望将“词典热更新”作为一个完整词进行匹配,需要热更新主词典。

操作步骤

  1. 创建名为 ext_main.dic 的主词典文件。词典文件每行包含一个词,例如:

    词典热更新
  2. 登录Lindorm管理控制台。

  3. 在页面左上角,选择实例所属的地域。

  4. 在实例列表页,单击目标实例ID或者目标实例所在行操作列的管理。

  5. 在左侧导航栏中,依次点击引擎管理 > 搜索引擎。

  6. 在页面顶部页签中,选择词典热更新,并单击更新词典文件按钮。

  7. 在主词典模块区域,将本地自定义词典文件直接拖拽至虚线框内,或点击虚线框选择文件,随后确认上传即可。

    重要

    主词典必须命名为:ext_main.dic后上传。

  8. 等待热更新生效。服务端会周期性检测词典文件是否更新,并在检测到更新时重新构建词典,建议等待 2 分钟。

  9. 使用 Analyzer API 验证主词典是否已更新。

    GET _analyze
    {
      "text": "词典热更新",
      "analyzer": "ik_smart"
    }

    如果分词结果将“词典热更新”识别为一个完整词,表示主词典已更新。

验证结果

词典更新完成后,重新写入示例环境中的 3 条数据,并使用相同的查询条件“词典热更新”再次查询。

查询结果中仅包含 _id=1 的数据。更新前 3 条记录均返回,更新后仅 _id=1 返回,说明“词典热更新”已作为完整词参与匹配。

更新停用词词典

使用场景

“吗”“的”“啊”等词不承载检索意图,参与查询会影响查询结果。可以通过更新停用词词典屏蔽这些词。

说明

本节示例沿用更新主词典章节创建的 testAnalyzer 索引,且主词典中已包含“词典热更新”。若要独立复现本节现象,需先完成示例环境的准备,并按需更新主词典。

问题复现

将查询条件改为“词典热更新吗”后执行以下查询。

GET testAnalyzer/_search
{
  "query": {
    "match": {
      "description": {
        "query": "词典热更新吗",
        "analyzer": "ik_smart"
      }
    }
  }
}

此时,_id=2 的数据也会返回,因为查询条件中的“吗”能够匹配“今天天气热吗”。

操作步骤

  1. 创建名为 ext_stopwords.dic 的停用词词典文件。词典文件每行包含一个词,例如:

    吗
  2. 登录Lindorm管理控制台。

  3. 在页面左上角,选择实例所属的地域。

  4. 在实例列表页,单击目标实例ID或者目标实例所在行操作列的管理。

  5. 在左侧导航栏中,依次点击引擎管理 > 搜索引擎。

  6. 在页面顶部页签中,选择词典热更新,并单击更新词典文件按钮。

  7. 在停用词模块区域,将本地自定义词典文件直接拖拽至虚线框内,或点击虚线框选择文件,随后确认上传即可。

    重要

    停用词必须命名为:ext_stopwords.dic后上传。

  8. 等待热更新生效。生效机制与更新主词典一致,服务端检测到词典文件更新后重新构建词典,建议等待 2 分钟。

  9. 使用 Analyzer API 验证停用词词典是否已更新。

    GET _analyze
    {
      "text": "词典热更新吗",
      "analyzer": "ik_smart"
    }

    如果分词结果中不包含“吗”,表示停用词词典已更新。

验证结果

词典更新完成后,重新写入示例环境中的 3 条数据,并使用相同的查询条件“词典热更新吗”再次查询。

GET testAnalyzer/_search
{
  "query": {
    "match": {
      "description": {
        "query": "词典热更新吗",
        "analyzer": "ik_smart"
      }
    }
  }
}

查询结果中仅包含 _id=1 的数据。更新前因“吗”匹配“今天天气热吗”而返回的 _id=2 不再返回,说明停用词词典已生效。