1. 程式人生 > >lucene 初探 - 查詢

lucene 初探 - 查詢

log ets 執行 () 準備 parser 技術分享 文件路徑 must

lucene初探, 是為了後面solr做準備的. 如果跳過lucene, 直接去看solr, 估計有點懵.

由於時間的關系, lucene查詢方法也有多個, 所以單獨出來.

一. 精確查詢

     /**
     * 獲取 查找對象
     * @return
     * @throws Exception
     */
    private IndexSearcher getSearcher() throws Exception {
        //1. 創建一個directory對象, 也就是索引庫存放的位置
        Directory directory = FSDirectory.open(new
File(indexDir)); //2. 創建一個indexReader對象, 需要指定directory IndexReader indexReader = DirectoryReader.open(directory); //3. 創建一個indexSearcher對象, 需要指定indexReader對象 IndexSearcher indexSearcher = new IndexSearcher(indexReader); return indexSearcher; } /** * 輸出信息到控制臺 *
@param indexSearcher * @param query * @throws Exception */ public void sout(IndexSearcher indexSearcher, Query query) throws Exception { //5. 執行查詢 TopDocs topDocs = indexSearcher.search(query, 5); //6. 返回查詢結果 ScoreDoc[] scoreDocs = topDocs.scoreDocs;
for (ScoreDoc scoreDoc : scoreDocs) { //獲取文檔id int doc = scoreDoc.doc; //根據文檔id獲取文檔 Document document = indexSearcher.doc(doc); //文件名字 String fileName = document.get("fileName"); //文件大小 String fileSize = document.get("fileSize"); //文件路徑 String filePath = document.get("filePath"); //文件內容 String fileContent = document.get("fileContent"); System.out.println("fileName : " + fileName); System.out.println("fileSize : " + fileSize); System.out.println("filePath : " + filePath); System.out.println("fileContent : " + fileContent); System.out.println("-----------------------"); } } /** * 精確查詢 * * @throws Exception */ @Test public void searchIndex() throws Exception { //1. 獲取查詢對象 IndexSearcher indexSearcher = getSearcher(); //2. 創建一個TermQuery對象, 指定查詢的域和查詢的關鍵詞 Query query = new TermQuery(new Term("fileName", "生活")); sout(indexSearcher, query); //3. 關閉IndexReader 對象 indexSearcher.getIndexReader().close(); }

在查詢的時候, 新建一個Term對象, 進去精確匹配. 前一篇提到過, 經過分詞器分下來的每一個詞或者一段話, 就是一個Term.

這裏在新建Term的時候, 傳入的是 域名 和 要搜索的詞.

這裏, 一個Term對象, 只有一個域, 那如果我想查詢多個域怎麽辦呢.

二. 組合查詢

/**
 * 組合查詢
 */
@Test
public void queryBoolean() throws Exception {
    IndexSearcher searcher = getSearcher();

    BooleanQuery query = new BooleanQuery();

    Query query1 = new TermQuery(new Term("fileName", "生活"));
    Query query2 = new TermQuery(new Term("fileContent", "生活"));

    query.add(query1, BooleanClause.Occur.MUST);
    query.add(query2, BooleanClause.Occur.SHOULD);

    //System.out.println(query);

    sout(searcher, query);

    searcher.getIndexReader().close();
}

這裏的Occur枚舉值, 有三個, must, should, must_not .

must : 相當於sql裏面的 and 連接

should : 相當於 or , 可有可沒有

must_not : 相當於 != , 不包含

這裏如果打印query, 會顯示: +fileName:生活 fileContent:生活

這是lucene的一種語法, lucene可以根據語法來查詢數據. 後面會提到. 如果是must_not , 則使用減號.

如: 將上面的query2使用 MUST_NOT 連接, 則顯示成: +fileName:生活 -fileContent:生活

三 . 查詢所有

一般查詢數據庫的時候, 都會提供一個 getAll 方法, 用於查詢滿足條件的所有數據, 當不傳條件時, 就查詢所有

lucene也提供了一個查詢所有的方法 : MatchAllDocsQuery

/**
 * 查詢所有
 *
 * @throws Exception
 */
@Test
public void queryAll() throws Exception {
    IndexSearcher searcher = getSearcher();

    Query query = new MatchAllDocsQuery();

    sout(searcher, query);

    searcher.getIndexReader().close();
}

四. 數值區間查詢

/**
 * 數值區間查詢
 *
 * @throws Exception
 */
@Test
public void queryNumericRange() throws Exception {
    IndexSearcher searcher = getSearcher();

    Query query = NumericRangeQuery.newLongRange("fileSize", 10L, 647L, true, true);

    sout(searcher, query);

    searcher.getIndexReader().close();
}

這裏的語法輸出就是 : fileSize:[40 to 647]

這是因為我後面兩個都設置為true, 表示包含關系. 如果都設置為false, 就是 {40 to 647}

五. 分詞器解析查詢

如前面提到的, 我輸入一句話查詢, 結果展示的結果卻並不是按照我輸入的全匹配結果.

那是因為在查詢之前, 對輸入的信息, 進行了分詞器解析, 然後根據解析結果, 再去查詢數據.

/**
 * 條件解析對象查詢
 *
 * @throws Exception
 */
@Test
public void queryParser() throws Exception {

    IndexSearcher searcher = getSearcher();

    QueryParser queryParser = new QueryParser("fileName", new IKAnalyzer());

    //Query query = queryParser.parse("*:*");
    Query query = queryParser.parse("fileName:這花好漂亮");
    //Query query = queryParser.parse("花");

    sout(searcher, query);

    searcher.getIndexReader().close();
}

*:* 表示查詢所有. 不管是哪個域.

fileName:這花好漂亮 : 表示在fileName域中, 將 "這花好漂亮" 分詞解析後, 進行查詢

花 : 在fileName域中, 查詢花. 因為在QueryParse創建的時候, 指定了域為 fileName

即使我在QueryParser裏面指定了要查詢的域, 但是在parse的時候, 我可以重新指定域.

這裏需要註意的是, 在上面數值區間查詢的時候, 如果我直接寫語法進去查詢, 是查不出來的. 因為數值類型變了. 通過語法輸進去, 變成字符串類型了.

技術分享圖片

從結果中可以看到, 我輸入 這花好漂亮, 查出來的卻是 軍中綠花. 這就是分詞的作用了.

六. 多域分詞查詢

/**
 * 條件解析對象查詢
 *
 * @throws Exception
 */
@Test
public void queryMultiParser() throws Exception {

    IndexSearcher searcher = getSearcher();

    String[] fields = {"fileName", "fileContent"};
    MultiFieldQueryParser queryParser = new MultiFieldQueryParser(fields, new IKAnalyzer());

    Query query = queryParser.parse("生活大爆炸");

    sout(searcher, query);

    searcher.getIndexReader().close();
}

多域分詞查詢, 沒啥好說的了.

lucene 初探 - 查詢