Lucene 提供豐富的 Query 實現,支援類 Google 的搜尋語法。本文系統整理五大進階查詢類型,並給出對應的 QueryParser 語法與低階 API 兩種使用方式。
| 操作符 | 語法示例 | 語義 | 備註 |
|---|---|---|---|
| OR | Java Lucene | 並集(預設空格即 OR) | 至少匹配一個詞 |
| AND | Java AND Lucene | 交集 | 必須同時包含 |
| NOT | Java NOT Lucene | 差集 | 不能單獨用 NOT Java |
| + | +Java Lucene | 強制包含 | 僅作用於緊後單詞 |
| - | Java -Lucene | 強制排除 | 等同 NOT |
// QueryParser 方式
Query q = new QueryParser("title", new StandardAnalyzer()).parse("+Java -Lucene");
限定查詢在特定欄位:
// 語法:fieldName:keyword
Query q = new QueryParser("title", new StandardAnalyzer()).parse("title:Lucene AND content:Java");
低階 API 組合:
BooleanQuery.Builder b = new BooleanQuery.Builder();
b.add(new TermQuery(new Term("title", "Lucene")), Occur.MUST);
b.add(new TermQuery(new Term("content", "Java")), Occur.MUST);
| 通配符 | 匹配規則 | 示例 | 匹配結果 |
|---|---|---|---|
| ? | 單字符 | t?ny | tiny, tony |
| * | 零或多字符 | Teach* | Teach, Teacher, Teaching |
// 低階 API(QueryParser 不支援開頭通配)
Query q1 = new WildcardQuery(new Term("title", "tex*"));
Query q2 = new WildcardQuery(new Term("title", "tex?"));
Query q3 = new WildcardQuery(new Term("title", "?ex*"));
效能警告:開頭通配(*abc)會掃描整個詞典,極其緩慢,生產環境慎用或啟用 ReverseStringFilter 反轉索引。
基於Levenshtein 編輯距離,允許拼寫錯誤:
// 語法:term~ 或 term~0.8 (相似度閾值 0~1)
Query q = new FuzzyQuery(new Term("title", "think")); // 編輯距離 ≤ 2
// 低階可調參數
FuzzyQuery fuzzy = new FuzzyQuery(new Term("title", "text"), 2, 0, 50);
適用於數值、日期、字串排序:
// 語法:field:[min TO max] (包含) 或 field:{min TO max} (不包含)
Query q = new QueryParser("birthDay", new StandardAnalyzer()).parse("birthDay:[20000101 TO 20060606]");
// 低階 API(Lucene 4+ 推薦 NumericRangeQuery)
Query numRange = NumericRangeQuery.newIntRange("age", 18, 35, true, true);
Query strRange = TermRangeQuery.newStringRange("name", "A", "M", true, true);
public TopDocs advancedSearch(IndexSearcher searcher, String keyword,
Integer minAge, Integer maxAge, String category) throws Exception {
BooleanQuery.Builder builder = new BooleanQuery.Builder();
// 關鍵詞全文搜尋(標題+內容)
if (keyword != null) {
QueryParser qp = new MultiFieldQueryParser(new String[]{"title","content"}, new StandardAnalyzer());
builder.add(qp.parse(keyword), Occur.MUST);
}
// 年齡範圍
if (minAge != null || maxAge != null) {
builder.add(NumericRangeQuery.newIntRange("age", minAge, maxAge, true, true), Occur.MUST);
}
// 精確分類
if (category != null) {
builder.add(new TermQuery(new Term("category", category)), Occur.FILTER); // 不計分,效能更好
}
return searcher.search(builder.build(), 20);
}
Occur.FILTER 或 ConstantScoreQuery 避免評分開銷;TopScoreDocCollector 而非 search(query, n);IndexReader.setDefaultQueryCache 緩存頻繁 Filter。