可以点击下面链接看之前写的es的学习:
1. 什么是倒排索引?
💡 知识点解析:
-
正排索引 (Forward Index): 就像书的"目录"。通过"章节名"找"页码"(通过 ID 找内容)。数据库的 ID 主键索引就是正排。
-
倒排索引 (Inverted Index): 就像书的"索引页/关键词表"。通过"关键词"找"页码"(通过内容找 ID)。
-
结构: 它是 ES 核心。它把文档拆分成一个一个的 Term(词条),然后记录每个词条出现在哪些文档里(Posting List)。
-
Term: "苹果" -> Doc1, Doc3
-
Term: "手机" -> Doc1, Doc2
-
🗣️ 面试参考回答:
"倒排索引是 Elasticsearch 的核心数据结构,它的设计是为了快速进行全文检索。
它的原理和书本末尾的'索引页'非常像:
-
分词: ES 会先把文档内容进行分词 ,拆解成一个个独立的词条(Term)。
-
映射: 然后建立一个'词条 '到'文档 ID 列表'的映射关系。
当我们搜索'苹果'时,ES 不需要遍历所有文档,而是直接去倒排索引中查找'苹果'这个词,立刻就能拿到包含该词的所有文档 ID,所以速度非常快。"
2. ES 中的文档、字段、索引分别是什么?
💡 知识点解析:
拿 MySQL 做类比最容易理解(虽然不完全准确,但面试够用):
-
Index (索引) ≈ MySQL 的 Table (表)(在旧版本类似 Database,但现在通常对标 Table)。
-
Document (文档) ≈ MySQL 的 Row (一行数据)。是 JSON 格式。
-
Field (字段) ≈ MySQL 的 Column (列)。
🗣️ 面试参考回答:
"我们可以用关系型数据库(MySQL)的概念来类比理解:
-
索引(Index): 类似于 MySQL 中的表(Table) ,是存储数据的逻辑容器。
-
文档(Document): 类似于 MySQL 中的行(Row) ,是 ES 中存储数据的基本单元,通常以 JSON 格式表示。
-
字段(Field): 类似于 MySQL 中的列(Column) ,是文档中的具体属性,比如 JSON 中的 key。"
3. 使用 ES 的时候你用的什么分词器,包含几种模式?
💡 知识点解析:
-
ES 默认的是 Standard 分词器,对中文很不友好(把"我是程序员"切成"我"、"是"、"程"、"序"、"员")。
-
中文开发必用:IK 分词器 (IK Analyzer)。
-
两种模式:
-
ik_smart: 聪明模式。切得少,粒度大。如"中华人民共和国"。 -
ik_max_word: 做最细粒度的拆分。如"中华人民共和国"、"中华"、"华人"、"共和国"...
-
🗣️ 面试参考回答:
"在项目中处理中文数据时,我们使用的是 IK 分词器 (IK Analyzer)。
它主要包含两种分词模式:
-
ik_smart: 智能切分,也是最粗粒度的切分。比如'程序员',它就切成一个词。适合用于搜索时的查询词分词。
-
ik_max_word: 最细粒度切分。它会将文本做穷尽式的拆分。比如'程序员',它可能会拆成'程序员'、'程序'、'员'。适合用于构建索引时,让索引覆盖面更广。"
4. 如何拓展词库?
💡 知识点解析:
-
场景: 来了个新词"奥利给",IK 分词器不认识,会切乱。需要教它。
-
静态方法: 改本地
ext.dic文件,重启 ES(太麻烦)。 -
动态方法(热更新): 配置一个远程 Web 服务器(Nginx),让 IK 分词器每分钟去请求一下
ext.dic。如果有更新(看 ETag 或 Last-Modified),就加载新词。
🗣️ 面试参考回答:
"拓展词库主要通过自定义字典来实现,通常是为了加入一些行业术语或网络热词。
我们在项目中采用了 IK 分词器的热更新 方案:
我们在配置文件中指定了一个远程的词典地址(通常是一个 Nginx 托管的 txt 文件)。IK 分词器会每隔一分钟发送请求检测该文件的 Last-Modified 或 ETag。如果发现文件变动,就会自动重新加载词典,无需重启 ES 服务。"
5. match 查询和 term 查询的区别?
💡 知识点解析:
-
match (匹配查询): 会分词。你搜"华为手机",它先切成"华为"和"手机",然后去搜既有华为又有手机的文档。
-
term (精确查询): 不分词。你搜"华为手机",它就去倒排索引里找"华为手机"这个完整的词。通常用于搜 ID、状态码、枚举值。
🗣️ 面试参考回答:
"它们的区别主要在于是否对搜索词进行分词:
-
match 查询: 是一种全文 检索查询。ES 会先用分词器把用户的搜索词(如'华为手机')拆分成多个 Term ('华为'、'手机'),然后再去倒排索引中匹配。
-
term 查询: 是一种精确查询 。ES 不会 对搜索词进行分词,而是直接拿着这个词去倒排索引里找完全一致的 Term。通常用于查询 ID、状态、标签等不需要分词的字段。"
6. ES 如何实现分页查询?
💡 知识点解析:
-
关键字:
from(跳过多少条),size(取多少条)。 -
类比 SQL:
limit offset, size。
🗣️ 面试参考回答:
"ES 的基础分页和 MySQL 类似,使用 from 和 size 两个参数。
-
from: 指定从第几条数据开始查(偏移量)。
-
size : 指定每页返回多少条数据。
例如 from=0, size=10 就是第一页;from=10, size=10 就是第二页。"
7. 深度分页的解决方案?
💡 知识点解析:
-
问题:
from + size默认限制是 10,000。如果你想查第 100 万页,ES 每一台机器都要查 100 万条数据并在内存里排序,内存会爆炸。 -
解决 1 (Search After): 推荐。像手机刷朋友圈,"下一页"是基于上一页最后一条的时间戳往后查。
-
解决 2 (Scroll): 快照。查的时候把此时此刻的所有结果拍个照存起来,慢慢翻。适合导出数据,不适合实时搜索(太耗资源,且不是实时的)。
🗣️ 面试参考回答:
"普通的 from + size 分页在深度分页(比如翻到第 1 万页后)时性能会急剧下降,且 ES 默认限制窗口最大为 10000。
针对深度分页,主要有两种解决方案:
-
search_after(推荐): 类似于'瀑布流'加载。它通过记录上一页最后一条数据的排序值(Sort Values),作为下一页查询的起点。它不需要在内存中跳过大量数据,性能很好,适合实时业务。
-
Scroll(游标): 类似于数据库的'快照'。它会一次性生成所有数据 的快照上下文,然后分批读取。适用于海量数据导出 或数据迁移场景,但不适合实时的用户查询,因为维护快照很耗资源。"
8. 怎么在 ES 中组合多个查询条件?
💡 知识点解析:
-
使用 Bool Query (布尔查询)。
-
四大金刚:
-
must: 必须满足(类似 AND)。算分。 -
should: 应该满足(类似 OR)。算分。 -
must_not: 必须不满足(类似 NOT)。不算分。 -
filter: 必须满足。不算分(只过滤,性能高,有缓存)。
-
🗣️ 面试参考回答:
"在 ES 中,我们主要使用 bool 查询 来组合多个条件。它包含四个核心子句:
-
must: 必须匹配(类似 AND),会计算相关性得分。
-
should: 选择性匹配(类似 OR),满足的条件越多得分越高。
-
must_not: 必须不匹配(类似 NOT),不计算得分。
-
filter: 必须匹配。但它不计算得分 ,且结果会被缓存。对于不需要算分的过滤条件(如按价格范围、按状态筛选),我们会优先放在 filter 中以提升性能。"
9. 全文检索查询结果默认是如何排序的,如何控制这个顺序?
💡 知识点解析:
-
默认: 按
_score(相关性得分)降序。 -
算法: 早期用 TF-IDF,现在默认用 BM25 算法。
-
控制: 使用
sort参数指定字段。如果用了sort,默认的_score就会变成 null(除非强制开启)。 -
复杂控制:
function_score,自定义脚本算分(比如竞价排名,给钱多的加分)。
🗣️ 面试参考回答:
"默认排序: ES 默认按照文档的相关性得分(_score) 进行降序 排列。这个得分是基于 BM25 算法计算的,简单说就是看搜索词在文档中出现的频率 和重要性。
如何控制:
-
指定字段排序: 可以在查询时使用 sort 参数,指定按照创建时间、价格等字段进行排序。
-
自定义算分(Function Score): 如果需要更复杂的排序(比如给'VIP用户'发布的文章加权),我们可以使用
function_score查询,通过自定义脚本 或权重函数来修改文档的最终得分。"