Lucene--搜索
一、創(chuàng)建查詢對象的方式
對要搜索的信息創(chuàng)建Query查詢對象,Lucene會根據(jù)Query查詢對象生成最終的查詢語法。類似關(guān)系數(shù)據(jù)庫Sql語法一樣,Lucene也有自己的查詢語法,比如:“name:lucene”表示查詢Field的name為“l(fā)ucene”的文檔信息。
可通過兩種方法創(chuàng)建查詢對象:
- 使用Lucene提供Query子類
Query是一個抽象類,lucene提供了很多查詢對象,比如TermQuery項(xiàng)精確查詢,NumericRangeQuery數(shù)字范圍查詢等。
如下代碼:
Query query = new TermQuery(new Term("name", "lucene"));
- 使用QueryParse解析查詢表達(dá)式
QueryParser會將用戶輸入的查詢表達(dá)式解析成Query對象實(shí)例。
如下代碼:
QueryParser queryParser = new QueryParser("name", new IKAnalyzer());
Query query = queryParser.parse("name:lucene");
二、通過Query子類搜索
2.1 TermQuery
TermQuery項(xiàng)查詢,TermQuery不使用分析器,搜索關(guān)鍵詞作為整體來匹配Field域中的詞進(jìn)行查詢,比如訂單號、分類ID號等。
private void doSearch(Query query) {
IndexReader reader = null;
try {
// a) 指定索引庫目錄
Directory indexdirectory = FSDirectory.open(new File(
"E:\\11-index\\0720"));
// b) 創(chuàng)建IndexReader對象
reader = DirectoryReader.open(indexdirectory);
// c) 創(chuàng)建IndexSearcher對象
IndexSearcher searcher = new IndexSearcher(reader);
// d) 通過IndexSearcher對象執(zhí)行查詢索引庫,返回TopDocs對象
// 第一個參數(shù):查詢對象
// 第二個參數(shù):最大的n條記錄
TopDocs topDocs = searcher.search(query, 10);
// e) 提取TopDocs對象中的文檔ID,如何找出對應(yīng)的文檔
ScoreDoc[] scoreDocs = topDocs.scoreDocs;
System.out.println("總共查詢出的結(jié)果總數(shù)為:" + topDocs.totalHits);
Document doc;
for (ScoreDoc scoreDoc : scoreDocs) {
// 文檔對象ID
int docId = scoreDoc.doc;
doc = searcher.doc(docId);
// f) 輸出文檔內(nèi)容
System.out.println(doc.get("filename"));
System.out.println(doc.get("path"));
System.out.println(doc.get("size"));
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
@Test
public void testTermQuery() throws Exception {
// 1、 創(chuàng)建查詢(Query對象)
Query query = new TermQuery(new Term("filename", "apache"));
// 2、 執(zhí)行搜索
doSearch(query);
}
2.2 NumericRangeQuery
NumericRangeQuery,指定數(shù)字范圍查詢.
@Test
public void testNumbericRangeQuery() throws Exception {
// 創(chuàng)建查詢
// 第一個參數(shù):域名
// 第二個參數(shù):最小值
// 第三個參數(shù):最大值
// 第四個參數(shù):是否包含最小值
// 第五個參數(shù):是否包含最大值
Query query = NumericRangeQuery.newLongRange("size", 1l, 100l, true,true);
// 2、 執(zhí)行搜索
doSearch(query);
}
2.3 BooleanQuery
BooleanQuery,布爾查詢,實(shí)現(xiàn)組合條件查詢。
@Test
public void booleanQuery() throws Exception {
BooleanQuery query = new BooleanQuery();
Query query1 = new TermQuery(new Term("id", "3"));
Query query2 = NumericRangeQuery.newFloatRange("price", 10f, 200f,
true, true);
//MUST:查詢條件必須滿足,相當(dāng)于AND
//SHOULD:查詢條件可選,相當(dāng)于OR
//MUST_NOT:查詢條件不能滿足,相當(dāng)于NOT非
query.add(query1, Occur.MUST);
query.add(query2, Occur.SHOULD);
System.out.println(query);
search(query);
}
組合關(guān)系代表的意思如下:
1、MUST和MUST表示“與”的關(guān)系,即“交集”。
2、MUST和MUST_NOT前者包含后者不包含。
3、MUST_NOT和MUST_NOT沒意義
4、SHOULD與MUST表示MUST,SHOULD失去意義;
5、SHOUlD與MUST_NOT相當(dāng)于MUST與MUST_NOT。
6、SHOULD與SHOULD表示“或”的概念。
三、通過QueryParser搜索
通過QueryParser也可以創(chuàng)建Query,QueryParser提供一個Parse方法,此方法可以直接根據(jù)查詢語法來查詢。Query對象執(zhí)行的查詢語法可通過System.out.println(query);查詢。
3.1 QueryParser
代碼實(shí)現(xiàn):
@Test
public void testQueryParser() throws Exception {
// 創(chuàng)建QueryParser
// 第一個參數(shù):默認(rèn)域名
// 第二個參數(shù):分詞器
QueryParser queryParser = new QueryParser("name", new IKAnalyzer());
// 指定查詢語法 ,如果不指定域,就搜索默認(rèn)的域
Query query = queryParser.parse("lucene");
System.out.println(query);
// 2、 執(zhí)行搜索
doSearch(query);
}
查詢語法:
1、基礎(chǔ)的查詢語法,關(guān)鍵詞查詢:
域名+“:”+搜索的關(guān)鍵字
例如:content:java
2、范圍查詢
域名+“:”+[最小值 TO 最大值]
例如:size:[1 TO 1000]
注意:QueryParser不支持對數(shù)字范圍的搜索,它支持字符串范圍。
數(shù)字范圍搜索建議使用NumericRangeQuery。
3、組合條件查詢
1)+條件1 +條件2:兩個條件之間是并且的關(guān)系and
例如:+filename:apache +content:apache
2)+條件1 條件2:必須滿足第一個條件,忽略第二個條件
例如:+filename:apache content:apache
3)條件1 條件2:兩個條件滿足其一即可。
例如:filename:apache content:apache
4)-條件1 條件2:必須不滿足條件1,要滿足條件2
例如:-filename:apache content:apache
第二種寫法:
條件1 AND 條件2
條件1 OR 條件2
條件1 NOT 條件2
3.2 MultiFieldQueryParser
通過MultiFieldQueryParser對多個域查詢。
@Test
public void testMultiFieldQueryParser() throws Exception {
// 可以指定默認(rèn)搜索的域是多個
String[] fields = { "name", "description" };
// 創(chuàng)建一個MulitFiledQueryParser對象
QueryParser parser = new MultiFieldQueryParser(fields, new IKAnalyzer());
// 指定查詢語法 ,如果不指定域,就搜索默認(rèn)的域
Query query = parser.parse("lucene");
//等同于name:lucene OR description:lucene
// Query query = parser.parse("name:lucene OR description:lucene");
// 2、 執(zhí)行搜索
doSearch(query);
}
四、TopDocs
Lucene搜索結(jié)果可通過TopDocs遍歷,TopDocs類提供了少量的屬性,如下:
注意:
- Search方法需要指定匹配記錄數(shù)量n:indexSearcher.search(query, n)
- TopDocs.totalHits:是匹配索引庫中所有記錄的數(shù)量
- TopDocs.scoreDocs:匹配相關(guān)度高的前邊記錄數(shù)組,scoreDocs的長度小于等于search方法指定的參數(shù)n