1. 同义词的核心概念
同义词功能的核心目的是:让不同的词或短语在搜索时被视为等价。
例如:
-
当用户搜索
手机时,结果也应该包含标有移动电话或cellular phone的文档。 -
搜索
番茄时,也能找到关于西红柿的内容。 -
对于品牌和通用名:
耐克和Nike。 -
对于缩写和全称:
北大和北京大学,UI和User Interface。
2. 同义词的工作阶段:索引时 vs. 查询时
这是理解同义词最关键的一点。同义词可以在两个阶段应用,各有优劣。
| 特性 | 索引时(Index Time) | 查询时(Search Time) |
|---|---|---|
| 工作原理 | 在文档索引(存入ES)时,同义词规则被应用到原始文本,扩展后的词项被直接存入倒排索引。 | 倒排索引中存储的是原始词项。在用户查询时,查询词会被同义词规则扩展,然后再去索引中匹配。 |
| 索引大小 | 更大。因为原始词和所有同义词都被存入了索引。 | 更小。索引中只存原始词。 |
| 查询性能 | 更快。查询时无需做任何扩展处理,直接查询。 | 稍慢。每次查询都需要进行同义词扩展,增加了一点开销。 |
| 灵活性 | 差。修改同义词规则后,必须重建索引(reindex)才能使新规则生效,非常麻烦。 | 极好。修改同义词文件后,只需重启分词器或使用 _reload_search_analyzers API 即可生效,无需重建索引。 |
| 推荐场景 | 数据一旦写入就不再变更,且同义词规则非常稳定的场景。现在一般不推荐使用。 | 绝大多数场景的推荐做法。数据频繁更新,同义词规则需要动态调整的场景。 |
3. 如何配置同义词
同义词功能是通过自定义分析器(Analyzer) 中的同义词分词过滤器(Synonym Token Filter) 来实现的。
步骤 1:定义同义词规则文件
创建一个纯文本文件(如 synonyms.txt),每行定义一条同义词规则。Elasticsearch 支持两种主要格式:
a) Solr 格式(显式映射)
使用 => 符号指定一组词的映射关系。
txt
# 将左侧的词映射为右侧的词(单向扩展) 手机, 移动电话 => 手机 西红柿 => 番茄
-
索引时:
移动电话会被替换为手机并存入索引。西红柿会被替换为番茄。 -
查询时:查询
移动电话会被替换为查询手机。
b) WordNet 格式(分组等价)
使用逗号分隔一组等价同义词。
txt
# 这一行的所有词互为同义词,会双向扩展 手机, 移动电话, 蜂窝电话, cellphone 番茄, 西红柿
-
索引时:任何一词都会被扩展为所有同义词(
手机, 移动电话, 蜂窝电话, cellphone)存入索引。(如果索引时使用,会导致索引巨大) -
查询时:查询任何一词都会被扩展为查询所有同义词。
最佳实践:对于查询时同义词,强烈推荐使用 Solr 格式进行单向映射,以避免查询过度扩展引入噪声。例如,将不常见的词映射到最 common 的词上。
步骤 2:将同义词文件放入 ES 配置目录
将 synonyms.txt 文件放到 Elasticsearch 所有节点的 config 目录下(如 /etc/elasticsearch/synonyms.txt)。
步骤 3:创建自定义分析器
在索引的 settings 中配置一个使用同义词过滤器(synonym)的自定义分析器。
json
PUT /my_index
{
"settings": {
"index": {
"analysis": {
"analyzer": {
"my_synonym_analyzer": { // 分析器名称
"tokenizer": "ik_max_word", // 这里示例使用IK中文分词器
"filter": [
"my_synonym_filter" // 应用我们自定义的同义词过滤器
]
}
},
"filter": {
"my_synonym_filter": {
"type": "synonym",
"synonyms_path": "synonyms.txt", // 同义词文件路径
"updateable": true // 关键!允许查询分析器动态重载同义词文件(ES 7.3+)
}
}
}
}
},
"mappings": {
"properties": {
"title": {
"type": "text",
"analyzer": "ik_max_word", // 索引时用的分词器
"search_analyzer": "my_synonym_analyzer" // 查询时用的分词器(应用同义词)
},
"content": {
"type": "text",
"analyzer": "ik_max_word",
"search_analyzer": "my_synonym_analyzer"
}
}
}
}
关键配置说明:
-
synonyms_path: 相对于config目录的路径。 -
updateable: 设置为true允许在不关闭索引的情况下,动态重载同义词文件(需要与_reload_search_analyzersAPI 配合使用)。 -
在
mappings中,为需要的字段指定search_analyzer为我们自定义的包含同义词的分析器。而analyzer(索引分析器)通常不使用同义词过滤器,以保持索引清洁。
4. 管理同义词(动态更新)
这是生产环境的关键。ES 7.3+ 提供了优雅的解决方案:
-
修改
config/synonyms.txt文件。 -
使用以下 API 通知索引重新加载搜索分析器(即查询时分析器):
json
POST /my_index/_reload_search_analyzers
执行后,所有新的查询都会立即使用新的同义词规则,无需停机或重建索引。
5. 高级技巧与注意事项
-
多词同义词(Synonyms with phrases):
对于像纽约和New York City这样的多词同义词,处理起来比较复杂。需要确保分词器能正确地将它们作为一个整体处理。通常需要配合使用flush_interval和分词规则。txt
纽约, "New York City"
-
区分大小写:同义词匹配默认是区分大小写的。
Apple(公司)和apple(水果)可能是不同的。确保你的同义词规则和文本处理流程保持一致(通常先统一转为小写)。 -
词干提取与同义词的顺序:如果你的分析链中同时有词干提取器(stemmer) 和同义词过滤器,通常建议先做同义词,再做词干提取。例如,先通过同义词将
running映射为sprinting,然后再对sprinting进行词干提取得到sprint。 -
测试你的分析器:使用
_analyzeAPI 来测试你的配置是否正确。json
GET /my_index/_analyze { "analyzer": "my_synonym_analyzer", "text": "我的移动电话" }检查输出结果是否包含你期望的同义词
手机。
总结
| 方面 | 建议 |
|---|---|
| 应用阶段 | 首选查询时(Search Time),灵活性极高。 |
| 规则格式 | 首选 Solr 格式(=>) 进行单向映射,更好控制。 |
| 文件管理 | 将 synonyms.txt 置于 config 目录,并设置 "updateable": true。 |
| 动态更新 | 使用 _reload_search_analyzers API 动态加载更改。 |
| 测试 | 务必使用 _analyze API 验证分析结果。 |
正确配置和使用同义词能极大提升搜索体验,使其更加智能和人性化。
1001

被折叠的 条评论
为什么被折叠?



