三亩地 三亩地SAN MU DI · CODE DIARY
ARTICLE DETAIL

日记详情

真实记录编程学习的某一天,欢迎挑你感兴趣的翻一翻。

es search包

es search包

好问题!有了 index 包的底子,看 search 包会顺畅很多。

---

search 包的入口:SearchService

跟 index 包一样,SearchService 是 search 包的"门面",所有搜索请求都会先经过它。

```java

// 搜索服务,每个节点都有一个

public class SearchService {

// 执行搜索

public SearchPhaseResult executeQueryPhase(...)

// 执行获取(取回 _source)

public SearchPhaseResult executeFetchPhase(...)

// 执行聚合

public SearchPhaseResult executeAggregationPhase(...)

}

```

从 SearchService 开始,你会看到这个流程:

```

SearchService.executeQueryPhase()

创建 Context(搜索上下文)

IndexSearcher(Lucene 搜索器)

Query 构建

执行搜索

返回结果

```

---

主线路径(跟着一个搜索请求走)

```

【协调节点】

TransportSearchAction

↓ 广播到所有分片

【数据节点】

SearchService.executeQueryPhase()

↓ 创建搜索上下文

SearchContext

↓ 构建 Lucene Query

QueryBuilder → Lucene Query

↓ 执行搜索

IndexSearcher.search(query)

↓ 返回结果

SearchPhaseResult

↓ 返回给协调节点

【协调节点】

SearchPhaseController.merge()

↓ 合并排序/分页/聚合

返回给用户

```

---

核心类一览

1. SearchService(入口门面)

每个节点上的搜索服务,所有搜索请求的入口。

2. SearchContext(搜索上下文)

一次搜索的上下文,包含查询、排序、聚合等所有信息。

3. QueryPhase(查询阶段)

执行 Lucene 搜索,返回文档 ID + 评分。

4. FetchPhase(取回阶段)

根据文档 ID,去 Lucene 取回 _source 等字段。

5. AggregationPhase(聚合阶段)

执行桶聚合、指标聚合等。

6. SearchPhaseController(协调控制器)

协调节点上,负责合并所有分片的结果。

---

建议的阅读顺序

```

第 1 步:SearchService

→ 找 executeQueryPhase 方法

→ 看它怎么创建 SearchContext

第 2 步:SearchContext

→ 看它里面装了什么(Query、Sort、Aggregations)

第 3 步:QueryPhase

→ 看它怎么把 QueryBuilder 转成 Lucene Query

→ 看它怎么调用 IndexSearcher.search()

第 4 步:FetchPhase

→ 看它怎么根据文档 ID 取回 _source

第 5 步:SearchPhaseController

→ 看它怎么合并多个分片的结果

```

---

一个具体的代码追踪路线

```java

// 1. SearchService 入口

public SearchPhaseResult executeQueryPhase(SearchShardRequest request) {

// 创建搜索上下文

SearchContext context = createContext(request);

// 执行查询

return queryPhase.execute(context);

}

// 2. QueryPhase

public SearchPhaseResult execute(SearchContext context) {

// 构建 Lucene Query

Query luceneQuery = context.query().toQuery(context);

// 执行搜索

IndexSearcher searcher = context.searcher();

TopDocs topDocs = searcher.search(luceneQuery, context.size());

// 返回结果

return new SearchPhaseResult(topDocs);

}

// 3. SearchPhaseController(协调节点)

public void merge(List<SearchPhaseResult> results) {

// 合并所有分片的结果

// 排序、分页、聚合

for (SearchPhaseResult result : results) {

merged.add(result);

}

return merged.sort().paginate();

}

```

---

为什么先看 index 包再看 search 包会更顺?

index 包 search 包

你知道 Lucene 怎么写 你看 Lucene 怎么读

你知道 IndexWriter 是什么 你知道 IndexSearcher 是什么

你知道 Document 是什么 你知道 TopDocs 是什么

你知道 Segment 是什么 你知道 Term 查询怎么工作

search 包的 QueryPhase 本质上就是在:

1. 把用户查询转成 Lucene Query

2. 调用 IndexSearcher.search()

3. 把 Lucene TopDocs 包装成 ES 结果

你看过 Lucene,这个过程你早就懂了!只是看 ES 怎么封装而已。

---

总结

问题 答案

从哪里开始? SearchService

核心类有哪些? SearchService, SearchContext, QueryPhase, FetchPhase, SearchPhaseController

主线路径? SearchService → SearchContext → IndexSearcher → 返回 → 合并

和 index 包的关系? 读依赖于写,所以先看 index 包

你的优势在哪? 懂 Lucene,知道 IndexSearcher 怎么工作

一句话:从 SearchService 开始,顺着 SearchService.executeQueryPhase() → QueryPhase → IndexSearcher.search() 这条线走到底。 你很快就能把整个搜索链路串起来。🚀

← 返回列表