网易首页 > 网易号 > 正文 申请入驻

老板让我做搜索功能,我不屑:“一句 SQL 不就搞定了?” 结果老板下跪:“给你n+5,求你走吧!”

0
分享至

你是小阿巴,刚入职的后端程序员。

这天,产品经理给你安排任务:阿巴阿巴,咱们网站要加一个文章搜索功能。

你心想:简单,直接写一句 SQL 查询数据库就搞定了~

SELECT * FROM article WHERE title LIKE '%关键词%'

结果上线没几天,就收到了大量用户的投诉!

  • 怎么什么搜索结果都没有啊?

  • 搜索结果乱七八糟,我想找的那篇内容竟然排在最后面?

  • 搜索一次竟然要等好几秒才出结果?什么破系统!

你汗流浃背了:明明 SQL 写对了啊,难道是 MySQL 数据库不行?


这时,号称 "后端之狗" 的鱼皮路过。他瞄了一眼你的代码,嘲笑道:肯定要用 Elasticsearch 来做搜索功能啊!

你一脸懵:Elasticsearch?那是啥?


第一阶段:认识 Elasticsearch

鱼皮:Elasticsearch 简称 ES,是一个专门为搜索而生的分布式数据库,也叫 搜索引擎数据库

它能存储和管理大量文本数据,提供快速、准确、灵活的全文检索功能。你刚才用 LIKE 查询搞不定的那些问题,用 ES 都能轻松解决。

你挠了挠头:真有这么神?

鱼皮:当然。打个比方,MySQL 就像图书馆的书架,书按照分类整整齐齐地摆放着,你想找某本书得自己一排一排去翻;而 ES 就像图书馆的电子检索系统,你输入关键词,它立刻就能告诉你书在哪儿,还会把最相关内容的排在最前面。


像全文搜索、日志分析、数据统计这些需要搜索能力的场景,ES 都能轻松搞定。


你眼前一亮:听起来有点儿夯啊,那我赶紧装一个试试。

第二阶段:实战应用 安装 Elasticsearch

机智如你,直接打开 ES 官网 下载了安装包:


并且成功安装运行:


你:安装好之后,我怎么操作它呢?

鱼皮:ES 本身提供了 RESTful API,默认在 9200 端口提供服务,你可以用 curl 命令或者 Postman 等接口测试工具直接发 HTTP 请求来操作它。


不过对新手来说,更推荐先安装一个官方的可视化工具 Kibana

有了它,你可以直观地查看分析数据、对数据进行操作。


只需要到官网下载安装包并运行,启动之后访问本机的 5601 端口,就能打开 Kibana 的管理界面了。在开发工具控制台里,你可以直接输入查询语句,能够立刻看到结果,非常方便。


基本操作

下面我来带你实操一波 ES 的基本操作。

1)首先是 创建索引。ES 的 索引(Index) 相当于 MySQL 里的表,是存放数据的容器。


创建索引的时候,还要定义 Mapping(映射),类似 MySQL 的表结构,用来规定每个字段的类型、是否需要分词、使用什么分词器等等。


在 Kibana 开发工具中输入这段代码:

PUT /article
{
"mappings": {
"properties": {
"title": { "type": "text", "analyzer": "standard" },
"content": { "type": "text" },
"tags": { "type": "keyword" },
"viewCount": { "type": "long" },
"isPublished": { "type": "boolean" },
"createTime": { "type": "date" }
}
}
}

这段代码创建了一个叫 article 的索引。其中 text 类型表示需要分词的文本字段,适合做全文检索;keyword 类型不会分词,适合存标签、状态这种需要精确匹配的内容。其他的类型就比较好理解了,long 存数字,boolean 存 true 或者 false,date 存日期。设计索引的时候要根据业务需求合理选择字段类型。

2)然后是 插入文档文档(Document) 相当于 MySQL 里的一行数据。ES 的文档是用 JSON 格式存储的,不需要像 MySQL 那样提前定义好所有字段,而是随时可以加新字段,非常灵活。

POST /article/_doc/1
{
"title": "鱼皮的 Elasticsearch 入门教程",
"content": "鱼皮带你学习 ES",
"cover": "封面图地址",
"tags": ["ES", "搜索"],
"viewCount": 1000,
"isPublished": true,
"createTime": "2025-01-30"
}

3)有了数据之后,就可以体验 ES 最核心的能力 搜索文档。比如在 article 索引中搜索标题包含 "鱼皮教程" 的文章:

GET /article/_search
{
"query": {
"match": { "title": "鱼皮教程" }
}
}

你执行完这条查询,惊喜地发现:搜 "鱼皮教程" 居然能匹配到 "鱼皮的 ES 入门教程" 这篇文章!


鱼皮点点头:虽然标题里并没有 "鱼皮教程" 这 4 个连着的字,但因为 ES 会自动分词,把 "鱼皮" 和 "教程" 拆开分别匹配,所以就搜到了。


你感叹道:哇,这才是搜索该有的样子啊!

查询语法 DSL

鱼皮:没错,ES 的搜索能力非常灵活强大。刚才你写的那些操作语句,其实用的就是 ES 的 DSL(Domain Specific Language 领域特定语言)。就像学数据库要学 SQL 一样,学 ES 就得学 DSL。不管是创建索引、插入文档,还是搜索查询,都是用这套 JSON 格式的语法来描述的。


其中最常用的就是查询语法,常见的查询类型有这么几种:

  • match 是全文检索,会对搜索词分词之后再匹配

  • term 是精确匹配,不分词,适合查 id、状态这种

  • bool 可以组合多个条件,用 must (必须满足)、 should (最好满足)、 must_not (必须不满足)来灵活控制

  • range 用来做范围查询,比如查某个时间段内的数据。

你不需要背这些语法,用到的时候问 AI 或者查文档就行,多写几次就熟了。

用代码操作 ES

你皱了皱眉:感觉写这些 JSON 格式的 DSL 还是有点麻烦啊,我用 Java 代码操作 ES 的时候,总不会也要手动拼这堆 JSON 吧?

鱼皮:当然不用!ES 官方提供了各种语言的客户端。比如你用 Java 语言,对应的是 Java API Client,支持链式调用和类型安全。


对于 Spring 项目来说,更推荐用 Spring Data Elasticsearch,它可以让你像用 MyBatis-Plus 操作 MySQL 一样操作 ES。只需要定义一个实体类,加上 @Document 注解指定要操作的索引,再写个 Repository 接口继承依赖包内置的 ES 操作接口。

@Document(indexName = "article")
public class Article {
@Id
private Long id;
private String title;
private String content;
}


public interface ArticleRepository extends ElasticsearchRepository {
// 根据标题搜索
List
findByTitle(String title);
}

框架会根据方法名自动生成查询逻辑,基本的增删改查方法就自动实现了。

// 使用示例
// 插入文档
articleRepository.save(article);
// 根据 id 查询
articleRepository.findById(1L);
// 根据标题搜索
articleRepository.findByTitle("鱼皮");
// 删除文档
articleRepository.deleteById(1L);

你感叹道:这才是人写的代码啊!优雅,真是优雅~ 我这就给 Java 代码整上 ES!

鱼皮:要注意,ES 版本更新很快,你用的客户端版本要跟安装的 ES 服务保持一致,不然会出各种奇奇怪怪的 Bug。


第三阶段:实用特性

学会了基本操作之后,你兴冲冲地把 MySQL 数据库里的文章数据全部导入到了 ES,然后把网站的搜索功能改成从 ES 查询。上线后效果立竿见影,搜索又快又准,用户好评如潮。


你非常开心:阿巴,俺可真厉害!


鱼皮:不错不错,你已经掌握了 ES 的基本操作,算是学会 80% 了。不过 ES 还有很多值得学习的实用特性,进一步优化你的搜索功能。

倒排索引

鱼皮:先来考考你,你知道为什么 ES 能搜得又快又准么?

你挠挠头:阿巴阿巴……

鱼皮笑道:关键在于它使用了 倒排索引 来存储数据,这是 ES 最核心的特性。

举个例子,假设咱们要存 3 篇博客文档,用 MySQL 数据库的话,存储结构是这样的:

文档 id

文档内容

1

感谢关注鱼皮

2

鱼皮是一名程序员

3

感谢关注编程导航

这种结构下,如果用户搜 “鱼皮程序员”,MySQL 会傻乎乎地把它当成一整个词去匹配,结果可能啥也搜不到。


而 ES 的做法不一样。它会先把文档内容按照单词进行切分,这个过程叫 分词。然后再构建 单词到文档 id 的映射关系,也就是 倒排索引


有了上述的倒排索引,当用户搜索 “鱼皮程序员” 时,搜索引擎数据库会先对搜索词进行分词,得到 “鱼皮” 和 “程序员”,然后根据这两个词汇就能找到文档 id 1、2 了。不用再一行一行遍历表内所有的数据,实现了更灵活、快速的 模糊搜索


你两眼放光:原来如此,牛啊牛啊!

但是 ES 怎么知道一句话该拆成哪些词呢?

分词器

鱼皮:好问题,这就要靠 分词器 了,它负责把一段文本拆成一个个词。

ES 内置了标准分词器,它基于 Unicode 文本分割算法设计,会按空格和标点符号等来切分文本。但这个规则只适合英文,对中文基本是一个字一个字地拆,效果很差。


所以如果你要做中文搜索,必须安装 IK 分词器。它是专门为中文设计的,能够智能识别中文词汇的边界,把句子正确地拆分成有意义的词语。

IK 提供了两种分词模式:

  • ik_smart 是智能分词,尽量把词分得少一点,比如 "好学生" 就只会拆成 "好学生" 一个词

  • ik_max_word 是最大化分词,能拆的都拆,"好学生" 会被拆成 "好学生"、"好学"、"学生" 三个词。

一般建议索引的时候用 ik_max_word 尽可能多分词,搜索的时候用 ik_smart 提高精确度。

此外,IK 还支持自定义词典。比如你想让 “程序员鱼皮” 作为一个完整的词不被拆开,加到词典里就行了。


高亮显示

你好奇道:既然 ES 能分词,那能不能在搜索结果中把命中的关键词标红啊?


鱼皮:当然可以,ES 支持 高亮显示 功能。只需要在查询里加个 highlight 参数,指定要高亮的字段就行:

GET /article/_search
{
"query": {
"match": { "title": "鱼皮教程" }
},
"highlight": {
"fields": { "title": {} }
}
}

返回结果里,命中的关键词会自动被 标签包起来,前端拿到之后加个颜色样式就搞定了。


你两眼放光:这也太方便了吧!


不过还有个问题,现在虽然能够搜索到内容了,但怎么把最相关的结果排到前面呢?

相关性评分

鱼皮:好问题。ES 会给每个搜索结果计算一个分数,放到 _score 字段中,分数高的排在前面。


你好奇道:这个分数是怎么算的呢?

鱼皮:ES 默认用的是 BM25 算法,主要考虑三个因素:

  • 词频 ,关键词在文档里出现的次数越多,分数越高。这很好理解,一篇文章里反复提到 "鱼皮",说明它很可能就是在讲鱼皮相关的内容。

  • 文档长度 ,同样出现一次关键词,在短文档里占的比例更大,所以短文档的分数会更高一点。

  • 稀有度 ,如果一个词在所有文档里都很常见,比如 "的"、"是",那它对搜索结果的区分度就不大。反过来,如果一个词很少见,只在少数文档里出现,那命中这个词的文档就更有价值,分数也更高。

聚合分析

鱼皮:除了搜索,ES 还有个很实用的功能叫 聚合分析,有点像 MySQL 的 GROUP BY 分组查询。

比如你想统计每个标签下有多少篇文章,写个聚合查询就行:

GET /article/_search
{
"size": 0,
"aggs": {
"tag_count": {
"terms": { "field": "tags" }
}
}
}

除了分组统计数量,ES 的聚合还能做求和、求平均值、找最大最小值、甚至多层嵌套聚合,能够满足开发各类数据报表的需求。


第四阶段:生产环境实践

用了一段时间 ES 后,你开始有点儿飘了。

没事儿就对着新来的实习生阿坤吹牛皮:ES 我闭着眼睛都能写!什么分词、高亮、聚合,我都玩得贼溜儿~


结果没多久,老板黑着脸找到你:有用户投诉,说明明改了自己文章的标题,但是搜索出来还是旧的,怎么回事?


你排查后发现:原来是 ES 里的数据和 MySQL 数据库里的不一样!当初俺只是把数据一次性导入 ES,后来文章在数据库里更新了,但 ES 里还是旧数据。

你有些头大:唉,ES 和 MySQL 是两套独立的系统,数据不会自动同步啊,咋办啊?


这时,旁边的阿坤突然鸡叫起来:我来!

数据同步方案

阿坤一边打篮球一边说:MySQL 和 ES 的数据同步,一般有这么几种方案。

1)定时任务

每隔几分钟扫一遍数据库,把最近更新的数据同步到 ES。优点是实现简单,缺点是有一定延迟。适合数据更新不频繁、对实时性要求不高的场景。


2)双写

每次把数据写入 MySQL 的时候顺便也写一份到 ES。优点是能做到实时同步,缺点是会影响写入性能,而且如果 ES 写失败了还得处理数据不一致的问题。适合数据写入量不大的场景。


3)用 Logstash

它是 ES 官方提供的数据收集工具,可以配置从 MySQL 定时拉取数据同步到 ES。优点是不用写代码,全靠配置驱动,缺点是需要额外部署组件,灵活性也有限。


4)用 Canal 监听数据库

Canal 是阿里开源的一个工具,它会伪装成 MySQL 的从库,实时监听数据库的变更日志。数据库一有改动,Canal 立刻就能感知到,然后同步到 ES。优点是能做到实时同步,缺点是部署和运维相对麻烦一点。


像咱们这个文章系统,更新又不频繁,用户也能接受几分钟的延迟,用定时任务就完全够了。如果以后做电商那种对实时性要求高的系统,再考虑上 Canal。

集群部署

鱼皮走过来拍了拍阿坤的肩膀:不错不错,我再考考你们,如果 ES 服务器挂了怎么办?

你支支吾吾:重…… 重启?


鱼皮摇头:用户等得起吗?

阿坤:生产环境肯定不能只部署一台 ES 啊,得搭建 集群

ES 集群中有几种角色的节点。主节点 负责管理集群的状态,比如哪些节点在线、索引的元数据等等。数据节点 负责存储实际的数据,处理读写请求。一般生产环境至少部署 3 个节点,保证高可用。


鱼皮追问:那如果数据量特别大,一个节点存不下怎么办?

你眼前一亮,终于等到自己会的问题了,抢答道:删除数据!

阿坤用看流浪狗的眼神看了你一眼,回答道:这就要说到 分片 了。分片就是把一个索引的数据拆成多份,分别存到不同的节点上。这样单个节点存不下的海量数据,也能通过多节点分担。而且多个节点可以并行处理查询请求,性能也更好。


你有些不服气:那万一某个节点挂了,上面的数据不就丢了?

阿坤:所以还需要 副本。副本就是分片的备份。每个分片可以配置若干个副本,存在其他节点上。万一某个节点挂了,副本可以顶上,这样数据就不会丢失,服务也不会中断。


其他生产实践

鱼皮拍了拍阿坤的肩膀:小伙子年轻有为啊!

这些都是 ES 在生产环境必须考虑的问题,此外还要学习:

  • 深度分页问题:ES 默认只允许查询前 10000 条数据,再往后翻就会报错。这是为了保护集群性能。如果确实需要给用户深度翻页,推荐使用更高效的 search_after。如果需要导出全量数据,可以结合 Point-in-Time API 使用。

  • 性能调优技巧:合理设计 Mapping,该用 keyword 的别用 text;查询的时候多用 filter 少用 query,因为 filter 会缓存结果;还有控制返回字段的数量,别动不动就查全部字段。

  • ELK 日志方案:ES 最经典的应用场景之一就是做日志系统。ELK 是三个组件的缩写,E 是 Elasticsearch 负责存储和搜索日志,L 是 Logstash 负责收集和处理日志,K 是 Kibana 负责可视化展示。大厂排查线上问题,基本都靠这一套。

你羞愧地抬不起头:我以为自己已经掌握了 ES,原来只是学了个皮毛……

鱼皮:小阿巴,你还要好好跟阿坤学习啊。


第五阶段:深入原理

被连环拷问后,你主动找到阿坤:坤哥,我想深入学习 ES 的底层原理,你是怎么学的?

阿坤有些惊讶:咦?你不背八股文的么?去 面试刷题网站 - 面试鸭 刷刷题就好了呀!


你震惊了:现在的实习生,竟然恐怖如斯!

鱼皮笑了笑:阿坤你别逗他了。其实可以带着问题去学习,比如 ES 为什么这么快

你抢答道:因为倒排索引!

鱼皮:没错,但这只是一方面。ES 底层是基于 Lucene 搜索引擎库的,它的倒排索引结构经过了高度优化。另外 ES 会把常用的数据缓存在内存里,查询时优先从内存读取,速度自然快。再加上 ES 是分布式的,可以把数据分片存储到多个节点,并行处理查询请求,几方面加起来,性能就上去了。


再比如数据是怎么写入的、查询请求是怎么执行的?

从这些问题出发,去阅读相关的文章,或者像阿坤说的刷一刷 ES 高频面试题,就能快速学会很多核心知识点。


如果想系统学习,推荐看 ES 官方文档,因为 ES 的更新太快了,很多书籍可能已经跟不上节奏了。


结尾

若干年后,你已经成为了公司的 ES 搜索专家。不仅能熟练使用 ES 解决各种搜索问题,搭个集群架构也是手拿把掐的。

你也像鱼皮当时一样,耐心地给新人分享学习 ES 的经验,让他们谨记一句话:ES 是实战型技术,一定要多动手实践!


再次遇到鱼皮是在一条昏暗的小巷,此时的他年过 35,灰头土脸。你什么都没说,只是给他点了个赞,投了 2 个币。


不打扰,是你的温柔~

一些对大家有用的资源:
100+ 编程学习路线 / 实战项目 / 求职指导
100+ 简历模板
300+ 企业面试题库 mianshiya.com
500+ AI 资源大全
1 对 1 模拟面试
动画学算法教程

特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。

Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.

相关推荐
热点推荐
拿下伊朗后,除过俄罗斯其它主要能源基本都被美国直接或间接掌控

拿下伊朗后,除过俄罗斯其它主要能源基本都被美国直接或间接掌控

邵旭峰域
2026-03-03 11:57:02
墨西哥女孩不听亲友劝阻远嫁中国,断了往来,5年后全家求援助

墨西哥女孩不听亲友劝阻远嫁中国,断了往来,5年后全家求援助

雅俗共赏1
2025-09-03 14:00:28
A股:紧急提醒2.5亿股民!从今天周二起,历史或许总是惊人的相似!

A股:紧急提醒2.5亿股民!从今天周二起,历史或许总是惊人的相似!

股市皆大事
2026-03-03 09:10:04
伊朗启动“马赛克防御”,关闭霍尔木兹海峡, 将打击所有船只

伊朗启动“马赛克防御”,关闭霍尔木兹海峡, 将打击所有船只

每日经济新闻
2026-03-03 09:05:52
中俄刚说打通图们江,第一个跳出来反对的,一点不让人意外

中俄刚说打通图们江,第一个跳出来反对的,一点不让人意外

闻香阁
2026-01-04 11:16:35
不可轻敌!武统台湾的难度远大于俄乌战争

不可轻敌!武统台湾的难度远大于俄乌战争

扶苏聊历史
2025-12-21 06:35:03
韩国网红博主上海旅游被宰客?一顿火锅花了177万韩币!

韩国网红博主上海旅游被宰客?一顿火锅花了177万韩币!

奋斗在韩国
2026-03-02 11:00:03
一场34分惨败,让开拓者看清杨瀚森,中国球迷开始理解斯普利特

一场34分惨败,让开拓者看清杨瀚森,中国球迷开始理解斯普利特

球场没跑道
2026-03-02 11:15:40
招聘员工要求 30 岁以下?哈啰致歉:坚决反对就业歧视

招聘员工要求 30 岁以下?哈啰致歉:坚决反对就业歧视

中国能源网
2026-03-03 10:43:07
“两伊战争中也未见过!”上百孩童惨死校园,护士抱起病人战火中转移

“两伊战争中也未见过!”上百孩童惨死校园,护士抱起病人战火中转移

澎湃新闻
2026-03-02 12:20:28
内贾德死亡真相

内贾德死亡真相

哲空空
2026-03-02 07:50:14
拉里贾尼:不会与美国进行谈判,美以不可能打了伊朗就一走了之!美官员承认:无情报显示伊朗计划“先发制人”打击美军

拉里贾尼:不会与美国进行谈判,美以不可能打了伊朗就一走了之!美官员承认:无情报显示伊朗计划“先发制人”打击美军

每日经济新闻
2026-03-02 14:22:17
救命,国产烂片又刷新下限了

救命,国产烂片又刷新下限了

喵喵娱乐团
2026-02-28 16:41:47
48小时内,美国两党罕见联手,公开怒斥特朗普:无权对伊开火!

48小时内,美国两党罕见联手,公开怒斥特朗普:无权对伊开火!

墨羽怪谈
2026-03-03 11:03:42
钱再多也没用!身价千万的撒贝宁,面对家庭牵挂烦心事还是太多了

钱再多也没用!身价千万的撒贝宁,面对家庭牵挂烦心事还是太多了

不甜的李子
2026-03-02 16:59:30
当今世界,哪些国家是世仇

当今世界,哪些国家是世仇

王鶔吃吃喝喝
2026-02-09 19:35:59
逃离三亚大溃败!一万四天价机票逼疯打工人,中产游客已穷哭

逃离三亚大溃败!一万四天价机票逼疯打工人,中产游客已穷哭

烈史
2026-02-26 14:51:59
回顾探花大神:害人害己,多位女主被亲戚认出当场“社死”

回顾探花大神:害人害己,多位女主被亲戚认出当场“社死”

就一点
2025-10-09 12:19:42
邹市明一家国外度假!冉莹颖膘肥体壮不好惹,轩轩一头白毛好土气

邹市明一家国外度假!冉莹颖膘肥体壮不好惹,轩轩一头白毛好土气

小徐讲八卦
2026-03-01 05:51:11
打到第3天,伊朗等来了中方支持

打到第3天,伊朗等来了中方支持

起喜电影
2026-03-03 11:58:21
2026-03-03 13:28:49
程序员鱼皮 incentive-icons
程序员鱼皮
一手科技资讯和编程干货
48文章数 57关注度
往期回顾 全部

科技要闻

手机AI在MWC上卷出了新高度

头条要闻

美国三架F-15E被击落 美军声明中有个非常奇怪的地方

头条要闻

美国三架F-15E被击落 美军声明中有个非常奇怪的地方

体育要闻

35轮后积分-7,他们遭遇史上最早的降级

娱乐要闻

谢娜霸气护夫:喊话薛之谦给张杰道歉

财经要闻

霍尔木兹海峡近乎停摆 布油直逼80美元

汽车要闻

长安汽车2月销量151922辆 环比逆势增长12.8%

态度原创

健康
游戏
亲子
教育
旅游

转头就晕的耳石症,能开车上班吗?

《三角洲》主播毁号事件后续!当事人征集联名控告

亲子要闻

深度长文:它们只能以超光速传播,完全颠覆人类的三观!

教育要闻

娃娃秧歌扭起来 非遗传承润童心

旅游要闻

从“观灯”到“玩灯” 达州“灯会+”激活夜经济新动能

无障碍浏览 进入关怀版