当前位置: 首页 > news >正文

Elasticsearch 入门教程:核心原理、Docker 部署与中文搜索实战

Elasticsearch 入门教程:核心原理、Docker 部署与中文搜索实战

做全文搜索功能,折腾了一圈 Elasticsearch,从装环境到调分词再到上线同步方案,踩了不少坑。这份 Elasticsearch 入门教程整理了从零到跑通的全部经历,希望能帮你少走弯路。点个收藏,我们开始。

一、Elasticsearch 是什么:不只是"搜索引擎"

Elasticsearch(简称 ES)是一个开源的分布式搜索与分析引擎,基于 Apache Lucene 构建。它存数据,但真正擅长的是对海量文本做近实时的全文检索——你可以把它理解为"给数据库装上了百度搜索"。

如果把 ES 和 MySQL 做一层概念映射,对应关系大致如下:

MySQLElasticsearch说明
DatabaseCluster一个 ES 集群对应一个数据库实例
TableIndex(索引)数据存储的逻辑单元
RowDocument(文档)最小数据单位,JSON 格式
ColumnField(字段)文档中的属性
SchemaMapping(映射)定义字段类型和索引方式

ES 7.x 之后,Type 的概念被废弃,一个 Index 下默认只保留_doc类型,架构比 6.x 清爽了不少。

ES 有几个让我觉得"真香"的特性:分布式架构天生支持横向扩展、数据写入后近实时可搜(默认 1 秒 refresh)、RESTful API 让任何语言都能调用、插件化设计可以按需扩展。这几个特性叠加在一起,让 ES 成了全文搜索领域的事实标准。

二、倒排索引:为什么 ES 搜得这么快

讲 ES 绕不开倒排索引——它是全文搜索能力的根基,不理解它,后面的分词器和查询优化都只能死记硬背。

2.1 什么是倒排索引

传统的"正排索引"是文档 → 关键词的映射,就像翻到一本书的某页去看这页写了什么。而倒排索引(Inverted Index)反其道而行之,是关键词 → 文档的映射——就像书末的索引页,查"分布式"三个字,直接告诉你出现在哪几页。

举个例子,假设有 3 篇文档:

  • 文档 1:Elasticsearch 是分布式引擎
  • 文档 2:分布式系统的核心是搜索
  • 文档 3:搜索引擎的未来是智能化

经过分词和归一化处理后,倒排索引长这样:

关键词文档 ID
elasticsearch1
分布式1, 2
系统2
搜索2, 3
引擎1, 3

当用户搜索"引擎"时,ES 直接查表定位到文档 1 和 3,不需要扫描全部文档——时间复杂度从 O(n) 降到了 O(1)。

2.2 倒排索引的构建过程

第一步:分词(Tokenization)。把原始文本拆成独立的词条。比如"Elasticsearch支持全文检索"拆成[elasticsearch, 支持, 全文, 检索]

第二步:归一化(Normalization)。对分词结果做标准化——转小写(Elasticsearch → elasticsearch)、去掉"的""是"这类停用词、做词干提取(running → run)。这一步直接决定了后续搜索的召回质量。

第三步:创建倒排列表。为每个词项建立到文档 ID 的映射关系,持久化存储。最终结构类似{"elasticsearch": [1], "分布式": [1, 2], ...}

2.3 用户搜索时发生了什么

当用户输入"分布式搜索"时,ES 的执行链路是这样的:查询词同样被分词(分布式 + 搜索)→ 分别查倒排索引(分布式 → [1,2],搜索 → [2,3])→ 按 AND/OR 逻辑合并结果 → 用 TF-IDF 或 BM25 算法算相关性评分并排序。整个链路在毫秒级完成,这就是倒排索引的威力。

三、分词器:搜索质量的命门

倒排索引的质量,很大程度上取决于分词器(Analyzer)。分词器决定了文本怎么拆、怎么存、怎么搜——它是在字符写入索引之前必须要经过的"安检通道"。

ES 的 Analyzer 由三个组件串联而成:

  1. 字符过滤器(Character Filters):预处理,比如去掉 HTML 标签、替换特殊字符(如把&转成and
  2. 分词器(Tokenizer):将文本按规则切分成一个个词项,这是整个流程中唯一必须的组件
  3. 词项过滤器(Token Filters):对词项做后处理——转小写、去停用词、词干提取等

ES 内置了多种分词器,我整理了一张场景对照表:

分词器分词方式中文效果适用场景
standard按词边界切分,转小写逐字拆分(差)英文通用场景
simple按非字母字符切分逐字拆分简单英文文本
whitespace仅按空格切分不分词大小写敏感场景
keyword不分词,整个输入作为单个词项不分词精确匹配(ID、状态码)
stopstandard + 过滤停用词逐字拆分英文长文搜索

注意到没?上面所有内置分词器对中文的处理都是"逐字拆分"——standard 会把"秋季穿搭指南"切成"秋、季、穿、搭、指、南"六个单字。这意味着搜"秋季"时,term 查询可能颗粒无收(后面第六章会详细演示这个坑)。这就是为什么必须装 IK 分词器。

四、Docker 部署 ES + Kibana:十分钟跑起本地环境

开发环境用 Docker 跑 ES 最省心——一行命令启动,不想要了直接docker rm -f清掉。以下基于 ES 7.3.0(2026 年 7 月实测可用)。

4.1 拉取镜像并单节点启动

# 拉取镜像dockerpull elasticsearch:7.3.0# 单节点启动dockerrun-d--namees7\-p9200:9200-p9300:9300\-e"discovery.type=single-node"\-eES_JAVA_OPTS="-Xms1024m -Xmx1024m"\elasticsearch:7.3.0
  • 9200:REST API 端口,外部调用走这个
  • 9300:集群内部节点间通信端口,单节点用不到但建议暴露
  • discovery.type=single-node:跳过主节点选举,单机开发必备
  • ES_JAVA_OPTS:设 JVM 堆内存为 1GB,建议不超过宿主机物理内存的一半

浏览器访问http://localhost:9200,返回 JSON 格式的集群信息就说明跑起来了。

4.2 挂载配置与数据,防止容器删除数据丢失

容器一删数据就没了,必须把关键目录挂载出来:

dockercpes7:/usr/share/elasticsearch/config E:\docker\elasticsearchdockercpes7:/usr/share/elasticsearch/data E:\docker\elasticsearchdockercpes7:/usr/share/elasticsearch/plugins E:\docker\elasticsearch

编辑config/elasticsearch.yml,加上跨域配置:

cluster.name:"my-es-cluster"network.host:0.0.0.0http.cors.enabled:truehttp.cors.allow-origin:"*"http.cors.allow-headers:Authorization,X-Requested-With,Content-Length,Content-Type

删掉旧容器,重新用带-v挂载的参数启动:

dockerrm-fes7dockerrun-d--namees7\-p9200:9200-p9300:9300\-e"discovery.type=single-node"\-eES_JAVA_OPTS="-Xms1024m -Xmx1024m"\-vE:\docker\elasticsearch\config:/usr/share/elasticsearch/config\-vE:\docker\elasticsearch\data:/usr/share/elasticsearch/data\-vE:\docker\elasticsearch\plugins:/usr/share/elasticsearch/plugins\elasticsearch:7.3.0

4.3 搭上 Kibana

Kibana 是 ES 官方的可视化和分析工具,它自带的 Dev Tools 是最好的 ES 查询练习环境。版本号必须和 ES 保持一致,否则有兼容性问题:

dockerpull kibana:7.3.0dockerrun-d--namekibana-p5601:5601 kibana:7.3.0

同样把配置文件复制出来,编辑kibana.yml

server.name:kibanaserver.host:"0"elasticsearch.hosts:["http://172.17.0.1:9200"]# 宿主机 IP,不是 localhosti18n.locale:"zh-CN"

注意:Kibana 在容器内访问 ES 时,localhost指向的是容器自身,必须用宿主机的实际 IP。Windows 下通常为172.17.0.1(用docker inspect es7可以确认)。

dockerrm-fkibanadockerrun-d--namekibana\-p5601:5601\-vE:\docker\kibana\config:/usr/share/kibana/config\kibana:7.3.0

访问localhost:5601,看到中文界面的 Kibana 控制台就成功了。左侧导航栏找到 Dev Tools 入口,后面所有查询都在这里写。

五、IK 中文分词器:让 ES 真正认识中文

最早用默认分词器建索引,上线后发现中文搜索效果很差——搜"美食"出来一堆不相关的结果。排查后才发现,"美食"被 standard 分词器拆成了"美"和"食"两个单字,匹配逻辑全乱了。

IK 分词器(IK Analyzer)是专为中文设计的 Lucene 分词插件,通过内置词典识别中文词组。你可以理解为"给 ES 装了一本现代汉语词典"——它知道"美食"是一个完整的词,而不是"美"+“食”。

5.1 安装与持久化

# 进入 ES 容器dockerexec-ites7 /bin/sh# 安装 IK(版本号与 ES 一致)bin/elasticsearch-plugininstallhttps://get.infini.cloud/elasticsearch/analysis-ik/7.3.0

安装时提示确认,输入y回车。看到-> Installed analysis-ik就装好了。

我踩过的坑:插件安装在容器内部,容器一删就没了。安装完一定要把插件文件复制到宿主机挂载目录:

dockercpes7:/usr/share/elasticsearch/plugins/analysis-ik E:\docker\elasticsearch\pluginsdockercpes7:/usr/share/elasticsearch/config/analysis-ik E:\docker\elasticsearch\config

这样配合第四章的-v挂载,插件就能持久化保留了。重启后查日志确认:

dockerrestart es7dockerlogs-fes72>&1|grepanalysis-ik

看到loaded plugin [analysis-ik]就说明插件已生效。

5.2 ik_smart vs ik_max_word

IK 提供两种模式,选择困难症友好——记住一句话:建索引用 ik_max_word(细粒度),搜索时用 ik_smart(智能分词)

模式策略输入"深度学习框架使用指南"的产出适用场景
ik_smart智能粗粒度[深度学习, 框架, 使用指南]搜索查询时使用
ik_max_word最细粒度穷举[深度学习, 深度, 学习, 框架, 使用, 指南]建索引时使用

_analyzeAPI 实际验证一下,左边 IK、右边 standard,差距一目了然:

# IK 智能分词POST /_analyze{"analyzer":"ik_smart","text":"这个技术博客写得怎么样?"}# 结果:这 / 个 / 技术 / 博客 / 写 / 得 / 怎么样# 默认 standard 分词POST /_analyze{"analyzer":"standard","text":"这个技术博客写得怎么样?"}# 结果:这 / 个 / 技 / 术 / 博 / 客 / 写 / 得 / 怎 / 么 / 样

IK 能识别"技术""博客"等中文词组,而 standard 只会逐字拆分——这在生产环境中意味着完全不同的搜索体验。

六、ES 基础查询语法:从增删改查到聚合搜索

理论都讲完了,下面该写查询了。

6.1 结构化建索引

先建一个笔记索引,指定每个字段的分词器:

PUT /note{"settings":{"number_of_shards":1,"number_of_replicas":1},"mappings":{"properties":{"title":{"type":"text","analyzer":"ik_max_word"},"content":{"type":"text","analyzer":"ik_max_word"},"create_time":{"type":"date","format":"yyyy-MM-dd HH:mm:ss"}}}}

Mapping(映射)相当于 MySQL 的建表语句——定义每个字段的类型和索引方式。这里titlecontent都用ik_max_word,意味着写入时会按最细粒度分词,提高搜索召回率。

插入几条测试数据:

PUT /note/_doc/1{"title":"夏日旅游攻略","content":"去海边玩耍的必备攻略,推荐三亚和青岛。","create_time":"2024-08-16 16:49:35"}PUT /note/_doc/2{"title":"美食笔记","content":"推荐几家成都的火锅店,真的很辣很过瘾!","create_time":"2024-11-02 17:00:36"}PUT /note/_doc/3{"title":"秋季穿搭指南","content":"分享适合秋天的服装搭配技巧,风衣必不可少。","create_time":"2024-11-03 16:59:58"}

6.2 增删改查速览

几个常用操作,一张代码块看完:

# 全量更新(文档存在则覆盖,不存在则插入)PUT /note/_doc/1{"title":"更新后的标题","content":"新内容"}# 只更新指定字段(推荐)POST /note/_update/1{"doc":{"title":"只更新标题"}}# 仅创建,已存在则报错PUT /note/_create/4{"title":"新文档","content":"测试"}# 删除DELETE /note/_doc/1# 查看单条GET /note/_doc/2# 搜索全部GET /note/_search

6.3 搜索:match vs term,一个常踩的坑

全文搜索用match——搜索词会先被分词再匹配:

GET /note/_search{"query":{"match":{"title":"穿搭"}}}# "穿搭"分词后匹配 → 命中文档 3

精确匹配用term——搜索词不经过分词,直接去索引里比对:

GET /note/_search{"query":{"bool":{"filter":{"term":{"title":"秋季"}}}}}

可能有人会问:用 term 搜"秋季",文档 3 标题明明包含"秋季穿搭指南",为什么一条结果都没有?

在项目中真遇到过的问题。原因出在分词环节:文档入库时title用了ik_max_word分词,“秋季穿搭指南"被拆成了多个词项。但term查询不做分词,直接用"秋季"这个完整字符串去索引里找——索引里存的是被 IK 拆散后的词项,很可能不包含完整的"秋季”。

换成match就能搜到,因为match会先把"秋季"分词后再分别匹配索引。一句话概括:match 分词后搜索(覆盖面广),term 原样匹配(精准但可能漏)。

6.4 分页、排序、聚合

# 分页:from = (page-1) * sizeGET /note/_search{"query":{"match_all":{}},"from":0,"size":2}# 按发布时间倒序GET /note/_search{"query":{"match_all":{}},"sort":[{"create_time":{"order":"desc"}}]}# 聚合:按发布时间分组统计文档数(类似 SQL 的 GROUP BY)GET /note/_search{"query":{"match_all":{}},"aggs":{"group_by_create_time":{"terms":{"field":"create_time"}}}}

补充一点:上面 term 查询用filter而非must,是因为filter不计算相关性评分_score,性能更好——适合"状态等于已发布""价格在 100-200 之间"这类纯过滤场景。

七、数据增量同步:怎么把 MySQL 的数据搬到 ES

生产环境中,MySQL 通常作为主存储,ES 作为搜索的从库。如何把 MySQL 的变更实时同步到 ES?业内主要两条路。

7.1 方案一:MQ 通知

业务服务在写 MySQL 的事务内,同时发一条 MQ 消息。搜索服务作为消费者监听消息,收到后更新 ES 索引。

这个方案的优势是灵活——消息体可以只携带变更字段,减少数据传输;MQ 自带持久化能力,搜索服务挂了消息不会丢。但代价是侵入性强——每个涉及搜索的业务点都要写 MQ 发送逻辑,团队大、服务多时维护成本不低。另外"数据库写成功但 MQ 发送失败"这种分布式事务问题也需要补偿机制兜底。

7.2 方案二:Canal

Canal是阿里巴巴开源的一个 MySQL binlog 增量订阅中间件。它的原理很巧妙——把自己伪装成 MySQL 的从库,监听主库的 binlog,解析出 INSERT/UPDATE/DELETE 事件后推送给下游消费者。你可以理解为"给 MySQL 接了一个监听器,数据一变它就通知你"。

Canal 最大的卖点是零侵入——业务代码一行不用改,直接订阅数据库日志就行。一致性也天然优于 MQ 方案,因为数据来源就是 binlog。但代价是运维成本高(Canal Server 需要独立部署和高可用),而且它只能感知到数据库层面的变更——如果你的同步逻辑涉及 Redis 缓存或外部 API 的数据加工,Canal 就无能为力了。

7.3 选型对比

对比维度MQ 通知方式Canal
实时性较高(受消费速率影响)近乎实时
数据一致性需要事务消息或补偿机制与数据库强一致
业务侵入性高,需在业务代码中埋点零侵入
开发成本需开发生产 + 消费两端逻辑需开发 binlog 解析与格式转换
运维成本中等(MQ 需高可用部署)较高(Canal Server 需独立部署与维护)
适用场景多数据源、复杂业务逻辑单一 MySQL 数据源、简单同步逻辑

可能有人会问:两种方案到底怎么选?

我的建议很简单:如果你只有一个 MySQL 数据源,同步逻辑就是"MySQL 多了/改了什么,ES 就跟着改",直接上 Canal,省心。但如果数据源不止 MySQL(比如还有 MongoDB、外部 API),或者同步前需要做字段拼装、多表关联等业务加工,那就选 MQ 方案——灵活性更高。我个人两个方案都在项目里用过:早期团队小、业务简单时用 Canal 确实省了不少事;后来数据源多了、同步逻辑复杂了,才切到 MQ。所以这不是"谁更好"的问题,而是什么阶段适合什么方案。


从倒排索引原理到 Docker 部署,从分词器到查询语法,再到数据同步方案,这篇 Elasticsearch 入门教程帮你把入门的坑都踩了一遍。这些内容在实际项目中够用了——剩下的高级功能(高亮搜索、Suggest 建议器、嵌套聚合等)建议在用到的场景下查官方文档,记忆效率更高。

系列下一篇计划写 Spring Boot 如何集成 Elasticsearch,覆盖 RestHighLevelClient 和 Spring Data Elasticsearch 两种方式,感兴趣的可以关注。

参考链接

  • Elasticsearch 7.3 官方文档(搜:Elasticsearch 7.3 Reference)
  • IK 分词器 GitHub(搜:elasticsearch-analysis-ik)
  • Canal GitHub(搜:alibaba canal)
  • Kibana 7.3 官方文档(搜:Kibana 7.3 Guide)

如果对你有帮助,欢迎点赞、收藏、转发。

http://www.cnnetsun.cn/news/3293974.html

相关文章:

  • Unity接入海康威视摄像头:SDK与VideoPlayer方案深度对比与低延迟实战
  • 西城微科蓝牙电子秤PCBA方案设计
  • 快速上手NS-USBLoader:5步搞定Switch游戏传输与RCM注入的终极免费工具
  • 如何快速配置TPFanCtrl2:ThinkPad用户的终极散热与静音指南
  • TI WEBENCH 滤波器设计工具 2024版:5步完成9阶Chebyshev低通滤波器设计
  • 2026年GEO优化代理值得做吗
  • PilotGo-plugin-logs高级功能:日志级别过滤与时间范围查询完全指南
  • DyscheOS-kernel社区贡献指南:如何参与开源操作系统开发
  • BiSheng JDK riscv部署指南:在RISC-V服务器上运行企业级Java应用
  • ADS 2023 谐波控制网络设计:CGH40010F 窄带 F 类功放 3 次谐波开路/短路实测
  • 别再盲目卷框架了,基础才是你的底气
  • PilotGo-plugin-logs故障排查:10个常见问题与终极解决方案大全
  • F5 LTM 4种部署模式实战对比:单机、HA Pair、集群与云部署选型指南
  • 5分钟掌握智慧教育平台电子课本高效下载方案
  • Midjourney提示词黄金公式曝光(含27个行业模板+137个参数组合对照表)——仅限本周开放下载
  • 终极指南:如何让你的老Mac焕发第二春,免费升级到最新macOS
  • Hadoop 3.3.5 HDFS 集群部署实战:3节点伪分布式环境搭建与核心服务验证
  • Pygame飞机大战实战:Python游戏开发入门与面向对象设计
  • 智慧树自动化学习:告别枯燥,重拾时间掌控权
  • 用 AtomCode 从零开发并部署上线:一个 Flask 待办应用的完整实战
  • GPT-5.6 三档模型 + ChatGPT Work:Sol/Terra/Luna 选型与企业级 Agent 接入实战
  • 如何用Wonder3D快速创建3D模型:5步完成高质量3D转换终极指南
  • 国家中小学智慧教育平台电子课本解析工具:一键将在线教材转换为PDF的高效方案
  • CAN 2.0 位定时参数实战:基于 STM32CubeMX 配置 500kbps 波特率的 3 个关键步骤
  • 新能源汽车等电位测试:从国标GB 18384到产线EOL的5个关键验证步骤
  • Python 3.12 文本处理:5行代码实现单词排序去重,效率超C++方案?
  • 压电蜂鸣器与PIC18F4515的高效警报系统设计
  • 基于 Simulink 的弱电网条件下双向 DC-AC 逆变器的鲁棒电流控制仿真实战教程
  • MediaCrawler终极指南:一站式掌握七大自媒体平台数据采集
  • Excel 365 CONCAT函数实战:3步合并多单元格内容,保留换行符