在搜索场景中,用户使用不同词语表达同一概念(例如“手机”与“智能手机”),可能导致搜索结果不全。同义词功能将这些词语视为等同,以扩展搜索范围,提升搜索召回率和用户体验。
操作前检查清单
在执行同义词文件变更前,务必确认以下事项:
确认关键索引至少拥有一个副本分片,以保障服务在单节点重启期间的可用性。(删除词典时将引起集群重启)
监控并确认集群负载处于健康水平(建议:CPU使用率 < 60%,堆内存使用率 < 50%)。
连接集群,通过
GET /_nodes/stats/jvm?filter_path=nodes.*.jvm.mem.heap_*查看所有节点的CPU和堆内存使用率。
工作原理与决策指南
理解同义词的两种配置方式及其利弊,有助于做出正确的技术选型。
同义词语法规则
同义词文件必须为 UTF-8 编码的 .txt 文件。文件中的每一行定义一组同义词规则,支持以下两种格式:
等价同义词(Solr格式)
用英文逗号分隔的词语将被视为完全等价。搜索其中任意一个词,都会匹配包含这组词中任何一个的文档。# 示例:搜索“手机”、“智能手机”或“移动电话”时,效果相同。 手机,智能手机,移动电话 ipod,i-pod,i pod定向映射(WordNet格式)
使用=>将一组词语映射到一个标准词,通常用于归一化,即将不规范的用词指向规范用词。# 示例:将"usa"和"us"都映射到“美国”。 usa,us => 美国
两种配置方式对比与决策
支持通过上传文件或在索引配置中内联定义同义词两种方式,两种方式的对比如下表所示。
对比项 | 方式一:上传文件 | 方式二:内联定义 |
操作方式 | 上传TXT文件到ES集群,然后在索引 | 直接在索引 |
优点 |
|
|
缺点 | 已有索引无法动态加载新词典。 |
|
适用场景 | 词典内容稳定、不常变更,且需要在多个索引间共享的场景。 | 对可用性要求极高,或需要频繁、快速更新同义词的场景。 |
操作步骤
方式一:通过上传文件配置(可复用)
此方式适合词典相对固定的场景。
步骤一:上传同义词文件
以下示例通过filter过滤器配置同义词,使用测试文件aliyun_synonyms.txt,其内容为:begin, start。
登录阿里云Elasticsearch控制台,选择目标地域和资源组,然后单击目标实例ID。
在左侧导航栏,选择 配置与管理 > ES集群配置,在基础配置区域找到同义词配置,单击上传。
在弹出的面板中,单击配置,然后选择上传方式:
文件后缀必须是.txt,文件名包含大小写字母、数字和下划线,且长度不超过30个字符
上传文件:从本地选择同义词TXT文件。
添加OSS文件:输入Bucket名称和同义词文件名称后,单击添加。
限制:OSS Bucket必须与ES实例在同一地域。
单击保存,确认后执行。
步骤二:创建索引并引用同义词文件
等待实例状态恢复为正常,连接集群后创建索引,并配置其使用已上传的同义词文件。
PUT /aliyun-index-test
{
"settings": {
"index":{
"analysis": {
"analyzer": {
"by_smart": {
"type": "custom",
"tokenizer": "ik_smart",
"filter": ["by_tfr","by_sfr"],
"char_filter": ["by_cfr"]
},
"by_max_word": {
"type": "custom",
"tokenizer": "ik_max_word",
"filter": ["by_tfr","by_sfr"],
"char_filter": ["by_cfr"]
}
},
"filter": {
"by_tfr": {
"type": "stop",
"stopwords": [" "]
},
"by_sfr": {
"type": "synonym",
"synonyms_path": "analysis/aliyun_synonyms.txt"
}
},
"char_filter": {
"by_cfr": {
"type": "mapping",
"mappings": ["| => |"]
}
}
}
}
}
}不同版本的集群,其索引创建语法存在一定差异,请参见ES常见版本操作索引示例。
步骤三:配置同义词字段title
ES 7.0以下版本
PUT /aliyun-index-test/_mapping/doc { "properties": { "title": { "type": "text", "analyzer": "by_max_word", "search_analyzer": "by_smart" } } }ES 7.0及以上版本
PUT /aliyun-index-test/_mapping/ { "properties": { "title": { "type": "text", "analyzer": "by_max_word", "search_analyzer": "by_smart" } } }
步骤四:验证同义词效果
使用_analyze API验证分词器是否已正确加载同义词,假设同义词文件包含 begin,start。
GET /aliyun-index-test/_analyze
{
"analyzer": "by_smart",
"text":"begin"
}成功的返回结果应同时包含 begin 和 start 两个词元(token)。
{
"tokens" : [
{
"token" : "begin",
"start_offset" : 0,
"end_offset" : 5,
"type" : "ENGLISH",
"position" : 0
},
{
"token" : "start",
"start_offset" : 0,
"end_offset" : 5,
"type" : "SYNONYM",
"position" : 0
}
]
}步骤五:测试搜索效果
写入两份包含同义词的文档
PUT /aliyun-index-test/doc/1 { "title": "Shall I begin?" }PUT /aliyun-index-test/doc/2 { "title": "I start work at nine." }搜索其中一个词(例如
begin),可同时召回包含begin和start的文档。GET /aliyun-index-test/_search { "query" : { "match" : { "title" : "begin" }}, "highlight" : { "pre_tags" : ["<red>", "<bule>"], "post_tags" : ["</red>", "</bule>"], "fields" : { "title" : {} } } }返回结果:
{ "took" : 70, "timed_out" : false, "_shards" : { "total" : 1, "successful" : 1, "skipped" : 0, "failed" : 0 }, "hits" : { "total" : { "value" : 2, "relation" : "eq" }, "max_score" : 0.28247005, "hits" : [ { "_index" : "aliyun-index-test", "_type" : "_doc", "_id" : "1", "_score" : 0.28247005, "_source" : { "title" : "Shall I begin?" }, "highlight" : { "title" : [ "Shall I <red>begin</red>?" ] } }, { "_index" : "aliyun-index-test", "_type" : "_doc", "_id" : "2", "_score" : 0.25069216, "_source" : { "title" : "I start work at nine." }, "highlight" : { "title" : [ "I <red>start</red> work at nine." ] } } ] } }
方式二:在索引设置中内联配置(不便复用)
此方式将同义词规则直接写入索引配置,适合词典小且需要快速迭代的场景。
步骤一:创建索引并定义同义词
连接集群,在创建索引时直接将同义词规则定义在synonyms数组中。
PUT /my_index
{
"settings": {
"analysis": {
"analyzer": {
"my_synonyms": {
"filter": [
"lowercase",
"my_synonym_filter"
],
"tokenizer": "ik_smart"
}
},
"filter": {
"my_synonym_filter": {
"synonyms": [
"begin,start"
],
"type": "synonym"
}
}
}
}
}上述命令创建了一个名为 my_index 的索引,并配置了自定义文本分析,处理流程为:
当文本字段使用 my_synonyms 分析器时,ik_smart 分词器将输入文本切分成词元;lowercase 过滤器将所有词元转换为小写;my_synonym_filter 过滤器将小写后的词元(如 begin 或 start)映射到其同义词组(即两者都被视为同一个规范词)。
步骤二:配置同义词字段title
ES 7.0以下版本
PUT /my_index/_mapping/doc { "properties": { "title": { "type": "text", "analyzer": "my_synonyms" } } }ES 7.0及以上版本
PUT /my_index/_mapping/ { "properties": { "title": { "type": "text", "analyzer": "my_synonyms" } } }
步骤三:验证同义词效果
GET /my_index/_analyze
{
"analyzer":"my_synonyms",
"text":"Shall I begin?"
}返回结果:
{
"tokens" : [
{
"token" : "shall",
"start_offset" : 0,
"end_offset" : 5,
"type" : "ENGLISH",
"position" : 0
},
{
"token" : "i",
"start_offset" : 6,
"end_offset" : 7,
"type" : "ENGLISH",
"position" : 1
},
{
"token" : "begin",
"start_offset" : 8,
"end_offset" : 13,
"type" : "ENGLISH",
"position" : 2
},
{
"token" : "start",
"start_offset" : 8,
"end_offset" : 13,
"type" : "SYNONYM",
"position" : 2
}
]
}同义词操作对集群的影响
不同的同义词操作对集群的影响不同。了解以下区别,有助于根据业务需求选择合适的更新方式。
操作方式 | 是否触发集群重启 | 说明 |
增量更新(上传同名文件) | 否 | 上传与已有文件同名的同义词文件时,属于增量更新(热更新),不触发集群重启 |
控制台更新同义词词库(新文件名或删除文件) | 是 | 上传新文件名的同义词文件或删除已有文件后保存,会触发集群滚动重启 |
增量更新同义词文件(热更新)
当上传的同义词文件与已有文件同名时,系统执行增量更新(热更新),不会触发集群重启。新上传的文件直接覆盖原文件,新创建的索引将自动使用更新后的词库。
增量更新后,已有索引不会自动加载新词库。如需在已有索引中生效,需关闭后重新打开索引(Close/Open),或重建索引。
控制台更新词库触发集群重启
以下操作会触发集群滚动重启:
上传新文件名的同义词文件后保存。
删除已有同义词文件后保存。
若业务需要避免集群重启,建议使用 elasticsearch-analysis-dynamic-synonym 插件实现动态更新机制。
具体操作,请参见阿里云ES实现同义词动态更新。
滚动重启期间可能出现以下影响:
服务抖动:节点逐个重启期间,即使有副本分片,也可能出现查询延迟短暂升高或服务抖动。
服务中断风险:集群负载过高或索引没有副本等极端条件下,重启可能导致部分请求失败或短暂服务中断。
重启时长:重启和词库分发的总耗时取决于集群规模、数据量和负载,可能需要几分钟甚至更长时间。
配置生效期间的读写可用性
同义词配置提交后,实例进入生效中状态。在此期间:
实例的读写功能正常可用,不影响现有业务的数据读写操作。
仅同义词扩展功能暂时不生效,使用新同义词规则的搜索查询可能返回不完整的结果。
生效完成后,实例恢复正常状态,新创建的索引将自动使用更新后的同义词词库。
常见问题
配置或更新同义词后集群状态异常(Yellow)或变更卡住怎么办?
配置或更新同义词后,如果集群状态变为 Yellow 或后续变更卡住,通常由以下原因引起:
同义词文件格式不规范:文件中包含大写字母但未转换为小写,导致分析器(Analyzer)解析失败。
OpenStorePlugin 报错:同义词文件内容异常触发 OpenStorePlugin 错误,导致分片无法正常分配,集群状态异常并阻塞后续变更。
可以按照以下方法排查和解决:
检查并修正同义词文件:确认文件中所有单词均已统一转换为小写字母,修正后重新上传。
增加 lowercase 过滤器:在索引 Settings 的 analyzer filter 配置中增加
lowercase过滤器,确保分词时自动将词条转换为小写。示例配置:"filter": { "my_synonym_filter": { "type": "synonym", "synonyms_path": "analysis/your-dict-name.txt" } }, "analyzer": { "my_synonyms": { "filter": ["lowercase", "my_synonym_filter"], "tokenizer": "ik_smart" } }索引无法操作时的恢复:若因修改 Analyzer Filter 导致需要关闭或重建索引且影响生产环境,或在控制台无法执行操作时,可尝试通过强制重新分片等方式恢复集群状态:
POST /_cluster/reroute?retry_failed=true
使用 analysis-dynamic-synonym 插件进行同义词热更新有哪些风险?
开源插件 analysis-dynamic-synonym 支持从远程或本地文件动态加载同义词,无需重启集群即可使新的同义词规则生效。但该插件存在以下已知风险:
并发缺陷:在高并发查询和写入场景下,该插件可能导致 Elasticsearch 进程死锁,进而引起 CPU 使用率打满和服务不可用。
适用场景限制:在 Serverless 实例或对稳定性要求极高的生产环境中,谨慎使用该插件。启用前,建议先在测试环境中充分评估实际查询和写入负载下的稳定性表现,确认后再部署到生产环境。如果同义词更新频率不高,建议优先使用增量更新方式(上传同名文件),避免引入第三方插件的潜在风险。
关于该插件的详细使用方法,请参见阿里云ES实现同义词动态更新。