phase 5 part 3: mongodb, elasticsearch hybrid search, data-pipeline, nodejs BFF topics with verified examples

This commit is contained in:
Shikui Wang committed 2026-10-23 16:38:52 +08:00
1 parent 9eeb10aede
commit 075872e31e
27 files changed
+2405 -52

No files matched your search

+67
View File
@@ -0,0 +1,67 @@
---
id: backend.elasticsearch.interview
title: Elasticsearch 面试题
type: interview
domain: backend
stack: [elasticsearch]
tags: [Elasticsearch, 倒排索引, 混合检索, 面试]
level: intermediate
related: [backend.elasticsearch.search-hybrid]
week: [14, 16]
---
# Elasticsearch 面试题
## 基础
### 【基础】什么是倒排索引?
**参考答案**:从“词”到“包含该词的文档列表(及位置、词频)”的映射。写入时对文本分词建立倒排表,查询时分词后查表求交并、算分,所以全文检索快。
**追问**:为什么 ES 写入后不能立即搜到?→ 近实时:写入先进内存缓冲,`refresh`(默认约 1 秒)后生成新的段才可搜索;可以 `refresh=wait_for` 但会影响写入性能。
### 【基础】`text` 和 `keyword` 的区别?
**参考答案**:`text` 会分词,用于全文检索;`keyword` 不分词,用于精确匹配、过滤、排序和聚合。同一字段可以用多字段(`fields`)同时建两种。
**追问**:对 `text` 字段做 `term` 查询会怎样?→ 往往查不到,因为存储的是分词后的词项,而 `term` 查询不分词。
### 【基础】`must` 和 `filter` 的区别?
**参考答案**:都要求匹配;`must` 参与相关性算分,`filter` 不算分并且可以被缓存,适合租户、权限、状态、时间范围等条件。
**追问**:权限条件应该放哪里?→ `filter`,并且在向量检索中也要通过 `knn.filter` 传入。
## 进阶
### 【进阶】混合检索怎么做?为什么常用 RRF?
**参考答案**:关键词(BM25)和向量(kNN)分别召回,再融合。BM25 分数无上限、与查询相关,向量相似度在固定区间,直接加权需要归一化且不稳定;RRF 只用名次 `1/(k+rank)` 求和,简单稳健。融合后再用重排模型精排。
**追问**:服务端 RRF 和应用层 RRF 怎么选?→ 服务端少一次往返、写法简洁,但受版本和许可证限制;应用层灵活、可以融合来自不同系统(例如 ES + pgvector)的结果。
### 【进阶】映射需要修改怎么办?
**参考答案**:已有字段的类型和分词器不能修改。新建索引(新映射)→ `_reindex` 或从数据源重新导入 → 追平增量 → 校验 → 原子切换别名 → 保留旧索引以便回滚。
**追问**:重建期间的增量写入怎么处理?→ 双写到新旧索引,或者重建完成后按时间戳 / 版本号补齐差异再切换。
### 【进阶】中文分词怎么做?
**参考答案**:常用 IK 插件:写入用细粒度(`ik_max_word`),查询用粗粒度(`ik_smart`);维护业务词典和同义词;插件版本要与 ES 一致。内置 `cjk` 分析器按二元切分,可以作为没有插件时的方案。
**追问**:词典更新后要做什么?→ 新写入的数据按新词典分词,已有数据需要重建索引才会生效。
## 场景题
### 【场景题】RAG 知识库对型号、错误码检索不准,怎么改?
**参考答案**:引入关键词检索与向量检索混合(ES BM25 + kNN,RRF 融合 + 重排);业务词典保证型号不被切碎;权限作为 filter;同步链路保证数据新鲜;用标注集评估召回率。详见[知识库混合检索场景](scenarios/kb-search-sync.md)。
**追问**:怎么证明改进有效?→ 固定标注集,对比改动前后的召回率@K、MRR 以及最终回答的正确率。
### 【场景题】数据库中的数据怎么可靠地同步到 ES?
**参考答案**:常用方案:业务事务内写 outbox 表 → 投递到消息队列 → 幂等消费者写 ES(数据库主键作为 `_id`、带版本号防止旧数据覆盖新数据);或者用 CDC(读取数据库日志,如 Debezium / MongoDB 变更流)。失败重试 + 死信 + 定期对账。
**追问**:消息乱序导致旧版本覆盖新版本怎么办?→ 使用外部版本号(`version_type=external`)或写入前比较更新时间,只接受更新的版本。