ElasticSearch中高效中文分词实践指南
一、分词基础概念
当文档被存储到ElasticSearch中时,系统会使用分词器从文本内容中提取出多个词元(token),这些词元用于支持索引的构建和后续的搜索操作。ElasticSearch内置了多种分词器,但这些内置分词器对中文文本的处理效果并不理想。下面通过实际案例来展示内置分词器的处理差异。
首先,我们向ElasticSearch发送一个REST请求,测试英文文本的分词效果:
POST http://localhost:9200/_analyze
{
"text": "hello world"
}
请求成功后,系统返回如下结果:
{
"tokens": [
{
"token": "hello",
"start_offset": 0,
"end_offset": 5,
"type": "<ALPHANUM>",
"position": 0
},
{
"token": "world",
"start_offset": 6,
"end_offset": 11,
"type": "<ALPHANUM>",
"position": 1
}
]
}
从上述结果可以看出,"hello world"被正确地分割为两个独立的单词,这是因为英文文本天然以空格作为分隔符,因此这种分词方式非常合理。
接下来,我们测试一段中文文本的分词效果:
POST http://localhost:9200/_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
},
{
"token": "一",
"start_offset": 5,
"end_offset": 6,
"type": "<IDEOGRAPHIC>",
"position": 5
},
{
"token": "生",
"start_offset": 6,
"end_offset": 7,
"type": "<IDEOGRAPHIC>",
"position": 6
},
{
"token": "产",
"start_offset": 7,
"end_offset": 8,
"type": "<IDEOGRAPHIC>",
"position": 7
},
{
"token": "力",
"start_offset": 8,
"end_offset": 9,
"type": "<IDEOGRAPHIC>",
"position": 8
}
]
}
从结果可以看出,内置分词器将每个汉字都独立分开,这种处理方式对于中文分词来说显然是不合理的,因为它无法识别词语和短语。默认情况下,ElasticSearch使用名为"standard"的分词器处理文本,这可以通过显式指定analyzer参数来确认:
POST http://localhost:9200/_analyze
{
"analyzer": "standard",
"text": "科学技术是第一生产力"
}
幸运的是,社区提供了多种优秀的第三方中文分词器,能够与ElasticSearch良好集成。在本文中,我们将重点介绍IK分析器的配置和使用方法。
二、IK分析器安装
ElasticSearch提供了插件管理脚本elasticsearch-plugin(在Windows系统下为elasticsearch-plugin.bat),该脚本位于ElasticSearch安装目录的bin目录下。该脚本支持三种主要操作,通过参数进行区分:
- elasticsearch-plugin install 插件地址 - 安装指定插件到当前ElasticSearch节点
- elasticsearch-plugin list - 显示当前节点已安装的插件列表
- elasticsearch-plugin remove 插件名称 - 删除已安装的插件
安装IK分析器时,插件地址可以是远程URL(在线安装)或本地文件路径(离线安装)。对于IK分析器,无论是远程还是本地安装,都需要提供zip格式的安装包。需要注意的是,IK分析器的版本必须与ElasticSearch版本保持一致。本文以ElasticSearch 7.8.0为例,因此使用相同版本的IK分析器。
通过远程URL安装IK分析器的命令如下:
./bin/elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.8.0/elasticsearch-analysis-ik-7.8.0.zip
如果无法从远程下载,也可以使用本地文件进行安装。在Linux系统下,本地安装命令为:
./bin/elasticsearch-plugin install file:///home/user/elasticsearch-analysis-ik-7.8.0.zip
在Windows系统下,本地安装命令为:
elasticsearch-plugin.bat install file:///D:/user/elasticsearch-analysis-ik-7.8.0.zip
安装完成后,ElasticSearch的plugins目录下会出现一个analysis-ik目录(包含解压后的IK分析器文件),同时config目录下也会生成一个analysis-ik目录(用于存放自定义词典)。为了使插件生效,需要重启ElasticSearch服务。
新版本的IK分析器提供了两种分词器:ik_max_word和ik_smart,它们在分粒度和效果上有所不同。
三、IK分析器使用方法
首先,我们测试ik_max_word分词器的效果:
POST http://localhost:9200/_analyze
{
"analyzer": "ik_max_word",
"text": "科学技术是第一生产力"
}
系统返回的分词结果如下:
{
"tokens": [
{
"token": "科技",
"start_offset": 0,
"end_offset": 2,
"type": "CN_WORD",
"position": 0
},
{
"token": "技术",
"start_offset": 1,
"end_offset": 3,
"type": "CN_WORD",
"position": 1
},
{
"token": "科学技术",
"start_offset": 0,
"end_offset": 4,
"type": "CN_WORD",
"position": 2
},
{
"token": "是",
"start_offset": 4,
"end_offset": 5,
"type": "CN_WORD",
"position": 3
},
{
"token": "第一",
"start_offset": 5,
"end_offset": 7,
"type": "CN_WORD",
"position": 4
},
{
"token": "生产力",
"start_offset": 7,
"end_offset": 10,
"type": "CN_WORD",
"position": 5
},
{
"token": "生产",
"start_offset": 7,
"end_offset": 9,
"type": "CN_WORD",
"position": 6
}
]
}
接下来,我们测试ik_smart分词器的效果:
POST http://localhost:9200/_analyze
{
"analyzer": "ik_smart",
"text": "科学技术是第一生产力"
}
系统返回的分词结果如下:
{
"tokens": [
{
"token": "科技",
"start_offset": 0,
"end_offset": 2,
"type": "CN_WORD",
"position": 0
},
{
"token": "技术",
"start_offset": 2,
"end_offset": 4,
"type": "CN_WORD",
"position": 1
},
{
"token": "是",
"start_offset": 4,
"end_offset": 5,
"type": "CN_WORD",
"position": 2
},
{
"token": "第一",
"start_offset": 5,
"end_offset": 7,
"type": "CN_WORD",
"position": 3
},
{
"token": "生产力",
"start_offset": 7,
"end_offset": 10,
"type": "CN_WORD",
"position": 4
}
]
}
对比两种分词器的结果,可以明显看出ik_max_word比ik_smart提取的词汇更多粒度更细,但这也意味着使用ik_max_word会占用更多的存储空间。在实际应用中,应根据具体需求选择合适的分词器。
四、IK分析器自定义词典
在某些场景下,IK分析器内置的词典可能无法满足特定需求(如专业术语、品牌名称等)。IK分析器支持自定义词典功能,允许用户添加特定词汇,使系统能够正确识别这些词条。
以"人工智能技术发展迅速"为例,假设我们希望系统能够识别"智能技术"这一专业术语,可以按照以下步骤自定义词典:
- 创建一个扩展名为.dic的文本文件,每行包含一个自定义词条,例如创建custom_terms.dic文件:
智能技术
大数据
云计算
- 将上述文件保存到ElasticSearch安装目录下的config/analysis-ik目录中(可以创建子目录组织不同类别的词典)
- 修改IK分析器的配置文件IKAnalyzer.cfg.xml(位于config/analysis-ik目录),添加自定义词典配置:
<entry key="ext_dict">custom_terms.dic</entry>
- 重启ElasticSearch服务使配置生效
配置完成后,再次使用ik_max_word分词器测试"人工智能技术发展迅速":
POST http://localhost:9200/_analyze
{
"analyzer": "ik_max_word",
"text": "人工智能技术发展迅速"
}
系统返回的分词结果将包含自定义的"智能技术"词条。需要注意的是,ik_smart分词器可能无法识别所有自定义词条,这是因为其分词策略更为保守。
五、设置默认分词器
可以在创建索引时指定默认使用的分词器,避免每次查询时都需要显式指定。以下是设置ik_smart为默认分词器的示例:
PUT http://localhost:9200/my_index
{
"settings" : {
"index" : {
"analysis.analyzer.default.type": "ik_smart",
"analysis.search_analyzer.default.type":"ik_smart"
}
}
}
可以通过以下查询验证设置是否生效:
GET http://localhost:9200/my_index/_settings
响应结果将显示当前索引的配置信息,包括默认分词器的设置。