ES常识9:如何实现同义词映射(搜索)

news2025/5/20 11:14:56

在 Elasticsearch(ES)中实现同义词映射(如“美丽”和“漂亮”),核心是通过 同义词过滤器(Synonym Token Filter) 在分词阶段将同义词扩展或替换为统一词项,从而让搜索时输入任意一个同义词都能匹配到所有相关文档。以下是分步骤的实现方案,结合 ES8 的特性说明:

一、同义词处理的核心原理

ES 的同义词处理发生在 分词(Analysis)阶段,通过自定义分析器(Analyzer)中的 同义词过滤器 将输入的文本(无论是索引文档还是搜索词)中的同义词替换或扩展为统一词项。例如:

  • 索引文档时,若文档包含“美丽”,会被扩展为“美丽 漂亮”;
  • 搜索时输入“漂亮”,也会被扩展为“美丽 漂亮”,从而匹配到所有包含“美丽”或“漂亮”的文档。

二、同义词配置的关键步骤

1. 定义同义词规则

同义词规则需按 ES 支持的语法编写,常见格式为:

美丽, 漂亮 => 美丽  // 替换模式:将“美丽”和“漂亮”替换为“美丽”(保留一个词项)
# 或
美丽, 漂亮          // 扩展模式:将“美丽”或“漂亮”扩展为“美丽 漂亮”(保留所有词项)
  • => 符号表示替换(仅保留右侧词项);无符号表示扩展(保留所有词项)。
  • # 为注释行。
2. 创建包含同义词过滤器的自定义分析器

在 ES 中,需将同义词过滤器绑定到自定义分析器,并指定该分析器用于目标字段的索引和查询。

示例(通过 ES API 创建索引并配置分析器)

PUT /my_index
{
  "settings": {
    "analysis": {
      "filter": {
        "my_synonym_filter": {
          "type": "synonym",          // 同义词过滤器类型
          "synonyms_path": "synonyms.txt",  // 同义词文件路径(支持本地文件或远程 URL)
          "expand": true,             // 是否扩展同义词(默认 true)
          "lenient": true             // 忽略解析错误(如无效规则)
        }
      },
      "analyzer": {
        "my_synonym_analyzer": {
          "tokenizer": "standard",    // 基础分词器(如 standard、ik_max_word 等)
          "filter": [
            "lowercase",              // 小写转换(可选,根据业务需求)
            "my_synonym_filter"       // 绑定同义词过滤器
          ]
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "content": {
        "type": "text",
        "analyzer": "my_synonym_analyzer",   // 索引时使用的分析器
        "search_analyzer": "my_synonym_analyzer"  // 查询时使用的分析器(可与索引分析器不同)
      }
    }
  }
}
3. 同义词文件的存储与加载
  • 本地文件:将 synonyms.txt 放在 ES 节点的 config 目录下(如 config/synonyms.txt),需确保所有节点路径一致。
  • 远程文件(ES 8+ 支持):通过 synonyms_path 指定 HTTP/HTTPS URL(如 https://example.com/synonyms.txt),ES 会定期拉取更新(需配置 update_interval):
    "my_synonym_filter": {
      "type": "synonym",
      "synonyms_path": "https://example.com/synonyms.txt",
      "update_interval": "1h"  // 每小时检查一次更新
    }
    

三、索引阶段 vs 查询阶段应用同义词

同义词过滤器可在 索引时(分析文档内容)和 查询时(分析搜索词)应用,需根据业务需求选择:

1. 索引时应用(推荐场景:文档内容固定)
  • 配置:在 analyzer 中绑定同义词过滤器(索引和查询均使用该分析器)。
  • 效果:文档中的同义词会被预先扩展或替换,搜索时输入任意同义词均可匹配。
  • 优势:查询时无需处理同义词扩展,降低查询耗时。
  • 缺点:新增同义词需重新索引文档(否则旧文档无法匹配新同义词)。
2. 查询时应用(推荐场景:同义词规则频繁更新)
  • 配置:仅在 search_analyzer 中绑定同义词过滤器,索引时使用基础分析器。
  • 效果:文档内容保持原始词项,搜索时搜索词会被扩展为同义词。
  • 优势:同义词规则更新无需重新索引文档。
  • 缺点:查询时需处理扩展,可能增加查询耗时(尤其当同义词数量大时)。
3. 混合应用(平衡方案)

同时在索引和查询阶段应用同义词过滤器,但需确保两者的同义词规则一致,避免索引词项与查询词项不匹配。例如:

"mappings": {
  "properties": {
    "content": {
      "type": "text",
      "analyzer": "my_synonym_analyzer",       // 索引时扩展同义词
      "search_analyzer": "my_synonym_analyzer" // 查询时再次扩展同义词
    }
  }
}

四、验证同义词效果

通过 ES 的 _analyze API 验证分析器是否正确处理同义词:

示例(验证“美丽”的分词结果)

GET /my_index/_analyze
{
  "analyzer": "my_synonym_analyzer",
  "text": "美丽"
}

预期输出(扩展模式):

{
  "tokens": [
    { "token": "美丽", "start_offset": 0, "end_offset": 2 },
    { "token": "漂亮", "start_offset": 0, "end_offset": 2 }  // 同义词被扩展
  ]
}

预期输出(替换模式):

{
  "tokens": [
    { "token": "美丽", "start_offset": 0, "end_offset": 2 }  // 仅保留替换后的词项
  ]
}

五、动态更新同义词规则

若需动态更新同义词(如新增“好看”作为“美丽”的同义词),需执行以下步骤:

1. 更新同义词文件

修改 synonyms.txt 或远程文件,添加新规则:

美丽, 漂亮, 好看  // 扩展模式:三个词互为同义词
2. 刷新分析器(ES 8+ 支持)

通过 _indices/close_indices/open 重新加载分析器(需短暂关闭索引):

// 关闭索引
POST /my_index/_close

// 打开索引(自动重新加载同义词文件)
POST /my_index/_open

注意:关闭索引会导致该索引不可用,生产环境建议使用 滚动升级(Rolling Upgrade)双索引切换 避免停机。

六、注意事项与优化

1. 性能影响
  • 扩展模式会增加词项数量(如一个词扩展为 5 个同义词),可能导致索引体积增大和查询耗时增加。
  • 替换模式可减少词项数量,但需谨慎选择基准词(如统一为“美丽”),避免丢失语义。
2. 同义词规则维护
  • 避免规则冲突(如“苹果”既指水果又指品牌),可通过 上下文感知同义词(需结合 context 过滤器,ES 8.7+ 支持):
    "my_synonym_filter": {
      "type": "synonym",
      "synonyms": [
        "美丽, 漂亮 => #general",  // 通用上下文
        "苹果, 水果 => #fruit",     // 水果上下文
        "苹果, 手机 => #electronics" // 电子设备上下文
      ]
    }
    
3. 中文分词器适配
  • 若使用中文分词器(如 IK、SmartCN),需确保同义词过滤器在分词器之后执行(避免分词结果与同义词规则不匹配)。例如:
    "analyzer": {
      "my_synonym_analyzer": {
        "tokenizer": "ik_max_word",  // 中文分词器
        "filter": [
          "my_synonym_filter"        // 分词后应用同义词过滤器
        ]
      }
    }
    

总结

ES 中实现同义词映射的核心是通过 同义词过滤器 在分词阶段扩展或替换词项。关键步骤包括:

  1. 定义同义词规则(扩展或替换模式);
  2. 创建包含同义词过滤器的自定义分析器;
  3. 将分析器绑定到目标字段(索引和/或查询阶段);
  4. 验证分词效果并动态更新规则。

通过合理配置,可实现“美丽”和“漂亮”等同义词在搜索时的智能映射,提升搜索结果的相关性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2379926.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

BGP综合实验(2)

一、实验需求 1、实验拓扑图 2、实验需求 使用 PreVal 策略,让 R4 经 R2 到达 192.168.10.0/24 。 使用 AS_Path 策略,让 R4 经 R3 到达 192.168.11.0/24 。 配置 MED 策略,让 R4 经 R3 到达 192.168.12.0/24 。 使用 Local Preference 策…

代码随想录算法训练营 Day51 图论Ⅱ岛屿问题Ⅰ

图论 题目 99. 岛屿数量 使用 DFS 实现方法 判断岛屿方法 1. 遍历图,若遍历到了陆地 grid[i][j] 1 并且陆地没有被访问,在这个陆地的基础上进行 DFS 方法,或者是 BFS 方法 2. 对陆地进行 DFS 的时候时刻注意以访问的元素添加访问标记 //…

【占融数科-注册/登录安全分析报告】

前言 由于网站注册入口容易被黑客攻击,存在如下安全问题: 暴力破解密码,造成用户信息泄露短信盗刷的安全问题,影响业务及导致用户投诉带来经济损失,尤其是后付费客户,风险巨大,造成亏损无底洞…

【CF】Day62——Codeforces Round 948 (Div. 2) CD (思维 + LCM + 枚举因数 | 思维 + 哈希)

C. Nikita and LCM 题目: 思路: 非常好的思维题,顺便复习了一下快速枚举因数和lcm的性质 我们先来看答案的上界,即全选,此时说明 lcm(a1,a2,a3,...) > a_max 其中 a_max 为 a 中最大的数,那么如果答案不…

基于requests_html的python爬虫

前言:今天介绍一个相对性能更高的爬虫库requests_html,会不会感觉和requests有点联系?是的。为什么开始不直接介绍呢?因为我觉得requests是最基本入门的东西,并且在学习过程中也能学到很多东西。我的python老师在介绍这…

STM32:按键模块 传感器模块 以及 相关C语言知识(详细讲解)

目录 按键 传感器模块 C语言知识 C语言数据类型 C语言宏定义 C语言typedef C语言结构体 C语言枚举 按键 常见的输入设备,按下导通,松手断开 按键抖动:由于按键内部使用的是机械式弹簧片来进行通断的,所以在按下和松手的瞬…

C++23 std::mdspan:多维数组处理新利器

文章目录 引言C23简介std::mdspan的定义与特点定义特点 std::mdspan的优势零成本抽象的多维数据访问减少内存开销提高代码灵活性 std::mdspan的应用场景科学计算图形学 相关提案示例代码使用动态扩展使用静态和动态扩展 总结 引言 在C的发展历程中,每一个新版本都带…

基于高德MCP2.0的智能旅游攻略系统设计与实现

前言:旅游规划的技术革命 在数字化旅游时代,MCP2.0(Map-based Collaborative Planning)系统代表着旅游攻略技术的最新演进。作为对1.0版本的全面升级,MCP2.0通过深度整合高德地图API和智能算法,实现了从静…

【时时三省】(C语言基础)用函数实现模块化程序设计

山不在高,有仙则名。水不在深,有龙则灵。 ----CSDN 时时三省 为什么要用函数? 已经能够编写一些简单的C程序,但是如果程序的功能比较多,规模比较大,把所有的程序代码都写在一个主函数(main函数)中&#x…

Flink流处理:实时计算URL访问量TopN(基于时间窗口)

目录 代码分析 背景知识拓展 代码调优 1. 性能优化 1.1 使用 KeyedStream 和 ProcessWindowFunction 替代 windowAll 1.2 使用 ReduceFunction 优化聚合 2. 功能扩展 2.1 支持动态窗口大小 2.2 支持多维度统计 2.3 支持持久化存储 3. 代码可读性 3.1 提取公共逻辑 …

华为OD机试真题——考勤信息(2025A卷:100分)Java/python/JavaScript/C/C++/GO最佳实现

2025 A卷 100分 题型 本专栏内全部题目均提供Java、python、JavaScript、C、C++、GO六种语言的最佳实现方式; 并且每种语言均涵盖详细的问题分析、解题思路、代码实现、代码详解、3个测试用例以及综合分析; 本文收录于专栏:《2025华为OD真题目录+全流程解析+备考攻略+经验分…

Go语言测试用例的执行与分析

在软件开发过程中,测试用例是确保代码质量的关键环节。Go语言作为一种现代的编程语言,它内置了强大的测试框架,可以帮助开发者轻松编写和执行测试用例。本文将介绍如何在 Go 语言中编写、执行测试用例,并对测试结果进行分析。 ## …

MyBatis:动态SQL

文章目录 动态SQLif标签trim标签where标签set标签foreach标签include标签和sql标签 Mybatis动态SQL的官方文档: https://mybatis.net.cn/dynamic-sql.html 动态SQL 动态SQL是 MyBatis的强大特性之一,如果是使用JDBC根据不同条件拼接sql很麻烦,例如拼接…

游戏引擎学习第280天:精简化的流式实体sim

回顾并为今天的内容做铺垫 今天的任务是让之前关于实体存储方式的改动真正运行起来。我们现在希望让实体系统变得更加真实和实用,能够支撑我们游戏实际所需的功能。这就要求我们对它进行更合理的实现和调试。 昨天我们基本让代码编译通过了,但实际上还…

王树森推荐系统公开课 排序03:预估分数融合

融合预估分数 p c l i c k ⋅ p l i k e p_{click} \cdot p_{like} pclick​⋅plike​ 有实际意义,等于在曝光中点赞的概率。 p c l i c k ⋅ p c o l l e c t p_{click} \cdot p_{collect} pclick​⋅pcollect​ 同理。 按多种排名做 ensemble sort。 某电商的融…

网络I/O学习-poll(三)

一、为什么要用Poll 由于select参数太多,较于复杂,调用起来较为麻烦;poll对其进行了优化 二、poll机制 poll也是一个系统调用,每次调用都会将所有客户端的fd拷贝到内核空间,然后进行轮询,判断IO是否就绪…

k8s(12) — 版本控制和滚动更新(金丝雀部署理念)

金丝雀部署简介: 1、基本概念 金丝雀部署是一种软件开发中的渐进式发布策略,其核心思想是通过将新版本应用逐步发布给一小部分用户(即 “金丝雀” 用户),在真实环境中验证功能稳定性和性能表现,再逐步扩大发…

Google设置app-ads.txt

问题: 应用上架后admob后台显示应用广告投放量受限,需要设置app-ads.txt才行。 如何解决: 官方教程: 看了下感觉不难,创建一个txt,将第二条的代码复制进行就得到app-ads.txt了。 然后就是要把这个txt放到哪才可以…

docker安装rockerMQ

参考Docker部署RocketMQ5.x (单机部署配置参数详解不使用docker-compose直接部署)_rocketmq不推荐用docker部署-CSDN博客 镜像拉取 镜像地址: https://hub.docker.com/r/apache/rocketmq/tags 我在部署的时候最新发行版是5.1.0可以根据需求自行选择一个5.x的版本&a…

交叉引用、多个参考文献插入、跨文献插入word/wps中之【插入[1-3]、连续文献】

我们在写论文时,需要插入大量参考文献。 有时,一句话需要引用多个文献,如:[1-3]或者[1,3,4]这种形式多个文献插入、跨文献插入。 在上一篇文章中,我们提到可以直接打“-”或者“,”,但是word导出…