
上一篇【第29篇】索引文件格式详解Lucene 磁盘上的秘密下一篇【第31篇】词查询、模糊匹配与布尔查询摘要前面把索引怎么建、怎么存讲透了这回转到查询侧。一个查询从你敲的 “content:蓝牙 AND price:[100 TO 200]” 字符串到最后吐出带得分的文档列表中间要过 QueryParser 解析、Weight 预计算、Scorer 逐文档打分三道关。本文把这条链路画清楚再给你一张 Lucene 常用查询类型的菜单后面几篇就按这道菜单逐个点菜。一、一次查询的完整旅程用代码触发一次搜索只有一行searcher.search(query, n)但底下流水很长。我们拆成四步看// 第1步字符串 → Query 对象靠解析器QueryqnewQueryParser(content,analyzer).parse(蓝牙 AND 降噪);// 第2步Query → Weight预计算全局统计信息// 第3步Weight → Scorer逐文档打分器// 第4步Scorer 跑完TopDocs 收结果TopDocshitssearcher.search(q,10);把内部旅程画成图你写的字符串 │ QueryParser 解析语法树 → Query 对象 ▼ Query 对象 (如 BooleanQuery 包俩 TermQuery) │ createWeight()先读全局统计(df/totalTerm) ▼ Weight (携带预计算的 IDF 等) │ scorer()生成能遍历匹配文档的打分器 ▼ Scorer (逐文档给出 score) │ Collector 收集 TopN ▼ TopDocs(文档号 得分 列表)这套 Query → Weight → Scorer 的三段式是 Lucene 查询的骨架。理解它你后面看任何查询类型都不会迷路因为它们全是换个方式造 Weight 和 Scorer。二、Query查询的抽象表达Query 是个抽象类代表我要找什么样的文档。它不直接打分只描述查询意图。常见的子类TermQuery找一个词。BooleanQuery把多个子查询用 AND/OR/NOT 组合。PhraseQuery找连续的词序列带 slop 容差。RangeQuery / 数值范围找某个区间。FuzzyQuery带编辑距离容错的词查询。PrefixQuery / WildcardQuery前缀、通配。SpanQuery更精细的位置跨度约束。你手写代码时可以直接 new 这些 Query不依赖字符串也可以从 QueryParser 解析出来。生产里复杂查询往往直接构造 Query 对象避免字符串拼接出错。三、Weight查询的预算阶段Weight 是 Query 在真正打分前的准备阶段产物。它干的事主要是读取全局统计信息这个词在多少文档出现 df、总词频等把 IDF 这类不依赖具体文档的因子先算好。为什么要多这么一层因为打分公式比如 BM25里有一部分因子对所有文档通用IDF、queryNorm提前算一次比每篇文档都重算一遍划算得多。Weight 就是把公共部分预算出来的环节。这点在后面讲 BM25 和打分统计时会反复用到。【Weight 预计算了什么】 TermQuery(蓝牙) ├─ 读 df 蓝牙在多少文档出现 ├─ 算 IDF 越稀有越值钱 └─ 这些和具体文档无关先算好 → 给 Scorer 用四、Scorer逐文档打分的执行者Scorer 拿着 Weight 给的预算去倒排里遍历匹配的文档对每篇算出 score。它才是真正跑的部分。不同查询类型提供不同的 Scorer 实现TermQuery 的 Scorer 直接遍历该词的倒排链BooleanQuery 的 Scorer 把子 Scorer 按 MUST/SHOULD 组合起来求交求并再加权。Scorer 遍历时还有个聪明机制它不一定从文档 0 扫到末尾而是利用倒排链本身的有序性跳跃着取下一个匹配文档呼应咱们 017 篇手写的跳表求交。所以即使索引里有上亿文档只要匹配的少打分很快。五、常用查询类型大观菜单下面这张表是 Lucene 查询的菜单后面几篇会逐个上菜今天先混个脸熟查询类型一句话用途典型场景TermQuery精确找一个词最基础的单词检索BooleanQuery多条件 AND/OR/NOT 组合综合筛选PhraseQuery连续词序列容忍间隔上海交通大学短语RangeQuery区间数值/日期价格 100~200FuzzyQuery编辑距离容错拼写纠错PrefixQuery前缀输入联想WildcardQuery通配符模糊模式SpanQuery精细位置跨度词距约束MatchAllDocsQuery匹配全部遍历/统计【查询类型关系图】 Query(抽象) ┌──────┼───────┬────────┐ Term Boolean Phrase Range │ (组合子Query) (支持数值/日期) │ Fuzzy / Prefix / Wildcard (都是 Term 的变体)六、Collector谁来收结果Scorer 算出一篇篇带分的文档最终由 Collector 决定怎么收集。默认 TopScoreDocCollector 收集得分最高的 N 篇就是 search(q, 10) 的 10。但你也可以写自定义 Collector 干别的比如边遍历边做分组聚合、统计命中总数、或者收集某字段的去重值。Collector 是 Lucene 留给你的结果后处理扩展点后面 033 篇专门讲排序、Filter 和 Collector。【一次搜索的收尾】 Scorer 逐篇打分 → Collector 决定收哪些 ├─ TopScoreDocCollector留得分最高 N 篇 ├─ TotalHitCountCollector只数总数 └─ 自定义聚合 / 去重 / 分组本篇小结一个 Query 的旅程是 QueryParser 把字符串解析成 QueryQuery 经 createWeight 预计算全局统计得到 WeightWeight 生成 Scorer 逐文档打分最后 Collector 收成 TopDocs。这套 Query→Weight→Scorer→Collector 的链路是所有查询类型的共同骨架。今天也给你列了张查询菜单Term/Boolean/Phrase/Range/Fuzzy… 后面几篇就逐个点菜。下一篇先上最基础的三个词查询、模糊匹配与布尔查询。上一篇【第29篇】索引文件格式详解Lucene 磁盘上的秘密下一篇【第31篇】词查询、模糊匹配与布尔查询