IK 分词器默认的词库是通用的,但每个项目都有自己的专有名词------小红书里"显眼包""多巴胺穿搭",电商里"充氮气独立包装"------这些词 IK 默认会把它们切成一堆碎词,搜索体验很差。这篇文章覆盖 IK 分词器的四种自定义配置:扩展词词典(让 IK 认识你的专有名词)、停用词词典(过滤掉无意义的词)、MySQL 热更新词典(改词库不用重启 ES)、同义词词典(搜"笔记本"也召回"笔记本电脑")。
为什么默认词库不够用
默认分词:多巴胺穿搭 → ["多巴胺", "穿搭"] ← 能分出来
显眼包 → ["显", "眼", "包"] ← 拆碎了,搜"显眼包"召回不准
充氮气独立包装 → ["充", "氮气", "独立", "包装"] ← "充氮气"应该是一个词
专有名词被拆碎了之后,倒排索引里没有完整的 term,搜"显眼包"召回不到。需要让 IK 知道"'显眼包'是一个完整的词,别拆"。
找到 IK 配置目录
Docker 部署的 ES,IK 配置路径在:
/usr/share/elasticsearch/plugins/ik/config/
├── IKAnalyzer.cfg.xml ← 主配置文件,所有词典入口
├── main.dic ← IK 自带扩展词库
├── stopword.dic ← IK 自带停用词库
└── ...(拼音、繁体等可选模块)
建议把目录挂出来方便改:
bash
docker run -d \
--name es \
-p 9200:9200 \
-v ./es-plugins/ik:/usr/share/elasticsearch/plugins/ik \
elasticsearch:8.15.0
改完重启容器生效。下面所有的 .dic 文件都放在这个 config/ 目录下,和 IKAnalyzer.cfg.xml 同级。
完整配置一览
先把 IKAnalyzer.cfg.xml 的最终形态放这里------四种词典的入口都在这一处。后面每个小节分别讲对应文件怎么写。
xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
<comment>IK Analyzer 扩展配置</comment>
<!-- 扩展词词典:本地文件,改完重启 ES -->
<entry key="ext_dict">my_ext.dic</entry>
<!-- 停用词词典:本地文件,改完重启 ES -->
<entry key="ext_stopwords">my_stop.dic</entry>
<!-- 扩展词热更新:MySQL,不重启 -->
<entry key="remote_ext_dict">jdbc:mysql://host.docker.internal:3306/ik?useSSL=false&serverTimezone=Asia/Shanghai</entry>
<entry key="remote_ext_dict_table">ik_ext_dict</entry>
<entry key="remote_ext_dict_column">word</entry>
<!-- 停用词热更新:MySQL,不重启 -->
<entry key="remote_ext_stopwords">jdbc:mysql://host.docker.internal:3306/ik?useSSL=false&serverTimezone=Asia/Shanghai</entry>
<entry key="remote_ext_stopwords_table">ik_stop_dict</entry>
<entry key="remote_ext_stopwords_column">word</entry>
<!-- 统一刷新间隔(秒) -->
<entry key="remote_ext_dict_interval">60</entry>
</properties>
| entry | 干什么 | 更新方式 |
|---|---|---|
ext_dict |
扩展词(专有名词) | 改 .dic 文件 → 重启 ES |
ext_stopwords |
停用词(无意义词) | 改 .dic 文件 → 重启 ES |
remote_ext_dict |
扩展词热更新 | 改 MySQL → 等 60s 自动生效 |
remote_ext_stopwords |
停用词热更新 | 改 MySQL → 等 60s 自动生效 |
remote_ext_dict_interval |
刷新间隔 | 默认 60 秒 |
1 扩展词词典------让 IK 认识你的专有名词
在 config/ 下新建 my_ext.dic,一行一个词:
# my_ext.dic
显眼包
多巴胺穿搭
充氮气
程一口
独立包装
重启 ES 后验证:
bash
curl -X POST "http://localhost:9200/_analyze" \
-H 'Content-Type: application/json' \
-d '{ "analyzer": "ik_max_word", "text": "充氮气独立包装" }'
# 返回:["充氮气", "独立", "包装"]
# "充氮气" 被保留成完整词了 ✅
2 停用词词典------过滤掉无意义的词
在 config/ 下新建 my_stop.dic:
# my_stop.dic
的
了
是
在
和
也
就
都
吗
呢
吧
重启 ES 后验证:
bash
curl -X POST "http://localhost:9200/_analyze" \
-H 'Content-Type: application/json' \
-d '{ "analyzer": "ik_max_word", "text": "今天天气太热了" }'
# "了" 被过滤掉了 ✅
3 MySQL 热更新------改词库不用重启 ES
重启一次几分钟,词库经常变的话吃不消。IK 1.10.0+ 支持 MySQL 热更新:启动时加载,之后每隔 60 秒去查一次,有新词自动加载到内存。
建表
sql
CREATE DATABASE ik;
USE ik;
-- 扩展词表
CREATE TABLE ik_ext_dict (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
word VARCHAR(255) NOT NULL COMMENT '扩展词',
create_time DATETIME DEFAULT CURRENT_TIMESTAMP
);
INSERT INTO ik_ext_dict(word) VALUES ('显眼包'), ('多巴胺穿搭'), ('程一口');
-- 停用词表
CREATE TABLE ik_stop_dict (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
word VARCHAR(255) NOT NULL COMMENT '停用词',
create_time DATETIME DEFAULT CURRENT_TIMESTAMP
);
INSERT INTO ik_stop_dict(word) VALUES ('的'), ('了'), ('呢'), ('吧');
放 MySQL 驱动
bash
# 下载 mysql-connector-j,放到 plugins/ik/ 目录下(和 IK 的 jar 同级)
cp mysql-connector-j-9.2.0.jar ./es-plugins/ik/
配置项说明
| 配置 | 含义 |
|---|---|
remote_ext_dict |
JDBC 连接串(用户名密码用 &user=root&password=xxx 拼在 URL 里) |
remote_ext_dict_table |
扩展词表名 |
remote_ext_dict_column |
扩展词所在的列名 |
remote_ext_stopwords |
停用词 JDBC 连接串 |
remote_ext_stopwords_table |
停用词表名 |
remote_ext_stopwords_column |
停用词所在的列名 |
remote_ext_dict_interval |
刷新间隔(秒) |
用户名密码写 JDBC URL 里:
jdbc:mysql://host:3306/ik?user=root&password=123456&useSSL=false
重启 ES 后,往 MySQL INSERT 一条新词,等 60 秒,验证:
bash
INSERT INTO ik_ext_dict(word) VALUES ('新测试词');
# 等 60 秒后
curl -X POST "http://localhost:9200/_analyze" \
-H 'Content-Type: application/json' \
-d '{ "analyzer": "ik_max_word", "text": "新测试词在这里" }'
# "新测试词" 被完整保留 → 热更新生效 ✅
4 同义词词典------搜"笔记本"也召回"笔记本电脑"
同义词不归 IK 管,属于 ES 的 synonym token filter。
新建同义词文件
synonyms.txt 放在 ES 的 config/ 目录下(/usr/share/elasticsearch/config/,不是 IK 的 config),一行一组:
笔记本, 笔记本电脑, laptop
显眼包, 显眼, 显眼精
充氮气, 氮气填充
创建 Index 时配上同义词 filter
json
PUT /articles
{
"settings": {
"analysis": {
"filter": {
"my_synonym_filter": {
"type": "synonym",
"synonyms_path": "analysis/synonyms.txt"
}
},
"analyzer": {
"ik_synonym_smart": {
"tokenizer": "ik_smart",
"filter": ["my_synonym_filter"]
},
"ik_synonym_max_word": {
"type": "custom",
"tokenizer": "ik_max_word",
"filter": ["my_synonym_filter"]
}
}
}
},
"mappings": {
"properties": {
"content": {
"type": "text",
"analyzer": "ik_synonym"
}
}
}
}
搜"笔记本"时,ES 自动把"笔记本电脑"也加入查询,多种说法都能召回。
同义词文件更新后,新写入的数据立即生效,已有数据需要 reindex 重建索引。