简介:这份资源是适配 Elasticsearch 7.17.3 的 IK 中文分词器安装包,面向在 Windows 环境下部署搜索引擎、需要处理中文分词的开发者与运维人员。由于官方下载渠道网络时常不稳定,作者将整理好的插件包上传,方便直接取用,省去反复重试的麻烦。压缩包共 19 个文件,约 4.3MB,以 5 个 jar 核心依赖、11 个 dic 词典、1 个 xml 配置、1 个 properties 描述文件及 1 个 policy 安全策略文件为主;其中 jar 承载分词逻辑与 HTTP 通信依赖,dic 词典覆盖主词典、停用词、姓氏、量词、后缀及低频补充词等,config 目录下的 IKAnalyzer.cfg.xml 则用于扩展词与停用词的加载配置。目前已有 1135 人学习下载,适合需要快速完成中文分词环境搭建、并希望按需调整自定义词典的读者参考使用。
1. 为什么 Windows 上跑 ES 7.17.3,中文搜索总差点意思
在 Windows 上部署 Elasticsearch 7.17.3 之后,很多人第一件想做的事就是丢一段中文进去搜。结果发现:搜「数据库优化」能命中,搜「数据库调优」就查不到;搜「全文检索」四个字,它给你按单字拆成「全」「文」「检」「索」挨个匹配,返回一堆不相关的结果。这不是 ES 坏了,是默认的 standard 分词器根本不认识中文——它按 Unicode 规则把中文逐字切开,语义全丢了。
这个资源就是解决这件事的:elasticsearch-analysis-ik-7.17.3,IK 分词器在 7.17.3 这个具体版本上的 Windows 可用包。IK 是 Elasticsearch 中文生态里用得最广的分词插件,支持自定义词典、热更新词库、细粒度/粗粒度两种切分模式。它适合正在 Windows 上做中文搜索的开发者,尤其是已经装好 ES 7.17.3、不想换版本、只想把中文分词这块补齐的人。下面从安装、配置到排错,按我实际拆包的顺序讲一遍。
2. IK 分词器的安装与版本对齐:别让插件和 ES 打架
2.1 为什么版本号必须严格对齐
Elasticsearch 的插件机制有个硬性约束:插件版本必须和 ES 主版本完全一致。7.17.3 的 ES 只能装 7.17.3 的 IK,装 7.17.0 的会报版本不兼容,装 8.x 的直接启动失败。这不是「大概差不多就行」的事,ES 在启动时会校验插件的plugin-descriptor.properties里的elasticsearch.version字段,对不上就抛IllegalArgumentException,整个节点起不来。
我见过有人图省事,从别处拿了个 7.16 的 IK 包往 7.17.3 里塞,结果 ES 日志里刷了一屏failed to load plugin,排查半天才发现是版本号差了一个小版本。所以拿到这个 zip 之后,第一件事是确认你的 ES 版本:
# 在 ES 安装目录的 bin 下执行,确认版本号 elasticsearch.bat --version # 输出应该类似: # Version: 7.17.3, Build: default/tar/...如果输出不是 7.17.3,那这个包就不适合你,别硬装。
2.2 Windows 下的安装步骤
Windows 上 ES 的插件安装有两种方式:命令行安装和手动解压。命令行方式需要联网从仓库拉,国内网络环境下经常超时;手动解压方式更可控,也是这个 zip 包存在的意义。
具体操作:
# 1. 进入 ES 安装目录 cd D:\elasticsearch-7.17.3 # 2. 在 plugins 目录下新建 ik 文件夹 mkdir plugins\ik # 3. 把 zip 解压到 plugins\ik 下 # 注意:解压后应该是 plugins\ik\plugin-descriptor.properties 这个层级 # 而不是 plugins\ik\elasticsearch-analysis-ik-7.17.3\plugin-descriptor.properties解压完检查一下目录结构,正确的应该是这样:
plugins/ ik/ elasticsearch-analysis-ik-7.17.3.jar plugin-descriptor.properties plugin-security.policy config/ IKAnalyzer.cfg.xml stopword.dic main.dic ...这里有个高频翻车点:很多人用解压工具时多套了一层文件夹,变成plugins\ik\elasticsearch-analysis-ik-7.17.3\...,ES 扫描插件时找不到plugin-descriptor.properties,直接报Plugin [ik] is not a plugin。解决办法就是把内层文件全部上移到plugins\ik\下。
2.3 重启与验证
装完之后必须重启 ES,插件只在启动时加载。重启后验证是否生效:
# 用 _analyze 接口测试 IK 是否工作 curl -X POST "http://localhost:9200/_analyze" -H "Content-Type: application/json" -d' { "analyzer": "ik_max_word", "text": "数据库优化方案" }'如果返回的 tokens 里出现了「数据库」「优化」「方案」这样的词,说明 IK 已经生效。如果报analyzer [ik_max_word] not found,那就是插件没加载成功,回去看 ES 启动日志里的 plugin 相关报错。
提示:Windows 下如果 ES 是以服务方式运行的,改完插件后要用
elasticsearch-service.bat restart重启服务,直接关窗口不算重启。
3. ik_max_word 与 ik_smart 的选型:两种切分模式怎么选
3.1 两种模式的行为差异
IK 提供两个分析器:ik_max_word和ik_smart。名字看着像玄学,实际区别在切分粒度。
ik_max_word会把文本做最细粒度切分,穷举所有可能的词。比如「中华人民共和国国歌」,它会切成「中华人民共和国」「中华人民」「中华」「华人」「人民共和国」「人民」「共和国」「国歌」等一堆。好处是召回率高,坏处是索引体积大、查询时匹配到的噪音多。
ik_smart做最粗粒度切分,只保留最合理的那个切分结果。同样一句话,它可能只切出「中华人民共和国」「国歌」。索引小、查询快,但召回率会低一些。
用_analyze接口能直观看到差异:
# ik_max_word 的切分结果 curl -X POST "http://localhost:9200/_analyze" -H "Content-Type: application/json" -d' { "analyzer": "ik_max_word", "text": "中华人民共和国国歌" }' # ik_smart 的切分结果 curl -X POST "http://localhost:9200/_analyze" -H "Content-Type: application/json" -d' { "analyzer": "ik_smart", "text": "中华人民共和国国歌" }'跑一下就能看到,ik_max_word返回的 token 数量明显多于ik_smart。
3.2 索引时和查询时的组合策略
实际项目里最常见的做法是:索引时用ik_max_word,查询时用ik_smart。这样索引阶段尽可能多地建立词条,保证召回;查询阶段用粗粒度减少噪音,保证精度。
在 mapping 里这样配:
{ "settings": { "analysis": { "analyzer": { "my_ik_analyzer": { "type": "custom", "tokenizer": "ik_max_word" } } } }, "mappings": { "properties": { "title": { "type": "text", "analyzer": "ik_max_word", "search_analyzer": "ik_smart" } } } }这里analyzer指定索引时的分析器,search_analyzer指定查询时的分析器。两个字段分开配,是 IK 在中文搜索里最实用的一个技巧。
3.3 自定义词典的加载
IK 支持扩展词典,把业务专有名词加进去,避免被切碎。配置文件在plugins\ik\config\IKAnalyzer.cfg.xml:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd"> <properties> <comment>IK Analyzer 扩展配置</comment> <entry key="ext_dict">custom/mydict.dic</entry> <entry key="ext_stopwords">custom/mystop.dic</entry> </properties>ext_dict指向扩展词典,路径相对于config目录。新建config\custom\mydict.dic,一行一个词,UTF-8 编码(不要带 BOM,否则第一个词会带乱码)。改完词典后,IK 支持热更新——在IKAnalyzer.cfg.xml里配一个remote_ext_dict指向一个 HTTP 地址,IK 会定时拉取。但本地文件方式的词典改动,需要重启 ES 才生效。
注意:词典文件必须是 UTF-8 无 BOM 编码。Windows 记事本默认可能带 BOM,用 VS Code 或 Notepad++ 转一下,否则会出现「明明加了词却切不出来」的诡异问题。
4. 避坑与排查:Windows 下 IK 装完不生效的几种情况
4.1 现象:ES 启动报 plugin 版本不兼容
原因:IK 包的版本和 ES 版本不一致。常见于从非官方渠道拿的包,或者 ES 升级后忘了换 IK。
解决:打开plugins\ik\plugin-descriptor.properties,看elasticsearch.version字段的值,必须和elasticsearch.bat --version输出的完全一致。不一致就换对应版本的 IK 包,别想着改配置文件蒙混过关,ES 还会校验 jar 包的哈希。
4.2 现象:_analyze 报 analyzer not found
原因:插件目录结构不对,ES 没扫描到。或者 ES 没重启。
解决:确认plugins\ik\plugin-descriptor.properties这个文件直接存在于ik目录下,不是嵌套在子文件夹里。然后确认 ES 确实重启了——Windows 下如果开了多个 ES 实例,可能你测的是另一个没装插件的实例。用curl http://localhost:9200/_cat/plugins?v看已加载的插件列表,里面应该有analysis-ik。
4.3 现象:自定义词典加了词但切不出来
原因:词典文件编码问题,或者路径写错,或者没重启。
解决:三步排查。第一,用file命令或编辑器确认词典是 UTF-8 无 BOM;第二,确认IKAnalyzer.cfg.xml里的路径相对于config目录是对的,比如写custom/mydict.dic就要有config\custom\mydict.dic;第三,本地词典改动必须重启 ES,热更新只对remote_ext_dict生效。
4.4 现象:搜索时中文被拆成单字
原因:mapping 里没指定 analyzer,用了默认的 standard。
解决:检查索引的 mapping,确认目标字段的analyzer设成了ik_max_word或ik_smart。已经建好的索引改 analyzer 需要重建索引(reindex),不能直接改。所以建索引之前就要把 mapping 定好,这是血泪经验。
4.5 现象:Windows 下 ES 服务启动后插件目录被锁
原因:ES 以 Windows 服务运行时,JVM 会持有插件 jar 文件的句柄,导致你无法覆盖或删除plugins\ik下的文件。
解决:先停服务elasticsearch-service.bat stop,再操作文件,改完再start。如果服务停不掉,去任务管理器结束elasticsearch-service-x64.exe进程。别在服务运行中硬删文件,会留下半损坏的插件目录,下次启动直接报错。
5. 进阶:用 reindex 平滑切换分词器与词典热更新的验证方法
5.1 已有索引换分词器的正确姿势
假设你有个索引articles_v1,字段content之前用的是 standard,现在想换成 IK。直接改 mapping 是不行的,ES 不允许修改已有字段的 analyzer。正确做法是建一个新索引,用 reindex 把数据搬过去。
# 1. 建新索引,mapping 里指定 IK curl -X PUT "http://localhost:9200/articles_v2" -H "Content-Type: application/json" -d' { "mappings": { "properties": { "content": { "type": "text", "analyzer": "ik_max_word", "search_analyzer": "ik_smart" } } } }' # 2. reindex 搬数据 curl -X POST "http://localhost:9200/_reindex" -H "Content-Type: application/json" -d' { "source": { "index": "articles_v1" }, "dest": { "index": "articles_v2" } }' # 3. 验证新索引的搜索效果后,用别名切换 curl -X POST "http://localhost:9200/_aliases" -H "Content-Type: application/json" -d' { "actions": [ { "remove": { "index": "articles_v1", "alias": "articles" } }, { "add": { "index": "articles_v2", "alias": "articles" } } ] }'用别名切换的好处是应用层不用改代码,始终查articles这个别名。reindex 期间老索引还在服务,切换是原子的,不会中断查询。
5.2 词典热更新的验证
如果你配了remote_ext_dict,IK 默认每 60 秒拉一次词典。验证热更新是否生效,可以这样做:
# 1. 先测一个词,确认当前切分结果 curl -X POST "http://localhost:9200/_analyze" -H "Content-Type: application/json" -d' { "analyzer": "ik_max_word", "text": "某个新词" }' # 2. 往远程词典里加上这个词,等 60 秒以上 # 3. 再测一次,看切分结果是否变化 curl -X POST "http://localhost:9200/_analyze" -H "Content-Type: application/json" -d' { "analyzer": "ik_max_word", "text": "某个新词" }'如果第二次结果变了,说明热更新生效。如果没变,检查remote_ext_dict的 URL 是否可访问、返回内容格式是否是每行一个词、HTTP 响应头里有没有Last-Modified(IK 靠这个判断是否更新)。
5.3 一个容易忽略的细节:词典优先级
IK 的词典加载顺序是:main.dic(主词典)→ext_dict(扩展词典)→ 用户自定义。后加载的不会覆盖先加载的,而是合并。所以如果你在主词典里已经有的词,在扩展词典里再写一遍,不会改变切分行为。真正需要干预切分的地方,是那些主词典里没有、但业务上必须作为整体出现的词,比如产品型号、内部术语。
我一般会在项目初期就把业务词表整理好,放进ext_dict,而不是等上线后发现问题再一个个补。补词典这件事,越晚成本越高——因为已经建好的索引不会自动重新分词,加词之后老数据还是按旧切分存的,得 reindex 才能让新词生效。
从那以后我每次装完 IK,都会先用_analyze跑一遍业务里最典型的几个查询词,确认切分符合预期,再往下做 mapping 和索引设计。这个习惯帮我省掉了好几次上线后才发现分词不对的返工。希望帮到你。
本文还有配套的精品资源,点击获取