這段話描述的是 Lucene/Elasticsearch 的 **Query Rewrite** 機制,核心一句話:
> **把“高級”或“邏輯”查詢(如 PrefixQuery、WildcardQuery、RangeQuery)在真正執行前,拆成最底層的、可直接倒排索引查的“原子查詢”(TermQuery、PointRangeQuery 等)。**
---
### 為什么要重寫?
1. **高級查詢本身無法直接走索引** ?
例:`PrefixQuery("titl", "jav")` 并不知道前綴 `jav*` 到底對應哪些詞項,需要先把索引里所有以 `jav` 開頭的真實 term 找出來。
2. **拆成原子查詢后可走優化路徑** ?
- 倒排列表直接求并集/交集 ?
- 可利用跳表、壓縮、緩存 ?
- 可以合并相鄰 TermQuery 為更高效的 BooleanQuery
---
### 舉個完整流程
```text
用戶寫的查詢 ? ? ? ? ? ?→ ? 重寫后的查詢
------------------------------------------------
PrefixQuery("title", "jav") ? → ? BooleanQuery
├── TermQuery("java")
├── TermQuery("javascript")
└── TermQuery("javaw")
```
- 重寫由 `Query.rewrite(IndexReader)` 觸發,發生在 **搜索執行早期**(QueryPhase 之前)。 ?
- 對上層透明:用戶看到的仍是原查詢,內部已變成“可執行的原子查詢”。
---
### Elasticsearch 中的體現
- 在 Profile API 里能看到 `rewrite_time` 指標。 ?
- 復雜查詢(wildcard、range、geo、script)都會經歷這一步;重寫結果會影響后續緩存鍵、性能分析。