前言

搜索和查询场景在企业里非常普遍,比如商品搜索、内容搜索、日志检索、客户检索、工单检索。面试常问:

  • 为什么不用数据库直接模糊查询。
  • ES 的倒排索引是什么。
  • 分词怎么选。
  • 高亮怎么做。
  • 深分页为什么慢。
  • 搜索结果怎么排序更合理。

这类题的重点是“搜索体验”和“查询性能”的平衡。

为什么需要搜索引擎

数据库擅长事务和精确查询,不擅长复杂搜索体验。

典型需求:

  • 多字段检索。
  • 分词搜索。
  • 相关性排序。
  • 高亮展示。
  • 复杂筛选。
  • 拼音、同义词、纠错。
flowchart TD
    A[用户输入关键词] --> B{是精确查询还是搜索}
    B -->|精确| C[数据库]
    B -->|搜索| D[ES]
    D --> E[分词]
    E --> F[倒排索引]
    F --> G[相关性排序]

倒排索引

倒排索引是 ES 的核心。

正排:文档 -> 词。
倒排:词 -> 文档列表。

这样搜索一个词时,不用扫描所有文档,而是直接找到包含该词的文档集合。

面试可以这样说:

ES 快的核心原因不是“单纯内存快”,而是倒排索引、分片并行、段结构和检索优化共同作用的结果。

索引设计

企业搜索建模时常常要考虑:

  • 哪些字段需要分词。
  • 哪些字段需要精确匹配。
  • 哪些字段需要排序。
  • 哪些字段需要聚合。
  • 哪些字段需要高亮。

常见字段类型思路:

需求 建议
标题搜索 text + 分词
ID、编码 keyword
状态 keyword
时间 date
价格 number
详情页内容 text

分词怎么选

分词器决定搜索体验。

常见方案:

  1. 标准分词器:通用,但中文效果一般。
  2. IK 分词器:中文场景常见。
  3. 拼音分词:适合名字、品牌、缩写。
  4. 同义词扩展:适合业务词汇。

对比:

方案 优点 缺点
标准分词 简单通用 中文体验一般
IK 中文效果较好 需要维护词库
拼音 方便用户拼写 索引体积增加
同义词 提升召回 容易误召回

检索、筛选、排序怎么组合

企业搜索一般不是只做关键词匹配,而是“检索 + 过滤 + 排序 + 分页”。

常见组合:

  • must:必须满足的关键词。
  • filter:不参与打分的过滤条件。
  • should:可选增强项。
  • sort:排序规则。
1
2
3
4
5
6
7
8
9
10
11
12
13
{
"query": {
"bool": {
"must": [
{ "match": { "title": "Java 面试" } }
],
"filter": [
{ "term": { "status": "PUBLISHED" } },
{ "range": { "publishTime": { "gte": "now-30d" } } }
]
}
}
}

面试重点:

  • 过滤条件尽量放 filter,不影响打分。
  • 复杂筛选要尽量结构化存储。
  • 搜索和筛选最好分层设计。

高亮怎么做

高亮的本质是把命中的词在结果中标出来,提升可读性。

常见场景:

  • 商品标题。
  • 文章标题和摘要。
  • 搜索结果摘要。

注意点:

  • 高亮会增加查询开销。
  • 高亮字段过多会拖慢响应。
  • 一般只对前几条和关键字段做高亮。

排序怎么设计

排序不能只按时间。

企业搜索常见排序维度:

  • 相关性。
  • 热度。
  • 时间。
  • 销量。
  • 权重。
  • 自定义业务分。

通常会做复合排序:

  1. 先按相关性得分。
  2. 再按业务权重。
  3. 再按时间。
flowchart TD
    A[搜索结果] --> B[相关性评分]
    B --> C[业务权重]
    C --> D[时间/销量/热度]
    D --> E[最终排序]

分页怎么处理

方案一:from + size

适合浅分页。

缺点:

  • 深分页很慢。
  • 大 offset 会让 ES 扫很多无用数据。

方案二:search_after

适合深分页和滚动加载。

优点:

  • 性能更稳。

缺点:

  • 不适合任意跳页。

方案三:scroll

适合批量导出、离线处理,不适合用户交互式搜索。

对比:

方案 适合 不适合
from + size 前几页 深分页
search_after 连续翻页 任意跳页
scroll 批量导出 前台搜索

ES 和数据库怎么配合

企业里搜索系统通常不会让 ES 独立承担所有数据真相。

常见模式:

  • 数据库是主库。
  • ES 是检索索引。
  • 写库后异步同步 ES。

同步方式:

  1. 应用双写。
  2. MQ 事件同步。
  3. Canal / binlog 同步。
  4. 定时补偿任务。
sequenceDiagram
    participant DB as 数据库
    participant MQ as 消息队列
    participant ES as Elasticsearch

    DB->>MQ: 数据变更事件
    MQ->>ES: 异步更新索引
    ES-->>MQ: 写入结果

常见高频题

为什么数据库不能直接做全文搜索?

因为数据库更擅长事务和精确查询,不擅长复杂分词、相关性排序和高亮展示。

ES 为什么适合搜索?

因为它用倒排索引、分片并行、相关性评分和搜索优化来支持复杂检索。

深分页为什么慢?

因为 ES 需要跳过大量前置结果,扫描和排序成本高。

搜索索引和数据库怎么保持一致?

常用 MQ 或 binlog 同步,再加补偿任务和对账校验。

搜索结果为什么要做业务排序?

因为纯相关性排序不一定符合业务目标,通常要结合热度、销量、权重和时间。

总结

搜索场景的回答可以围绕四条主线:

  1. 为什么用搜索引擎:倒排索引和复杂搜索体验。
  2. 怎么建模:分词、keyword、date、number、排序字段。
  3. 怎么查询:检索、过滤、排序、高亮、分页。
  4. 怎么同步:数据库主写、ES 做检索索引、MQ 或 binlog 同步。

真正的企业搜索不是“能搜到”,而是“搜得准、搜得快、搜得稳、好维护”。