1. 程式人生 > >Lucene筆記10-Lucene的搜尋-其他常用Query搜尋

Lucene筆記10-Lucene的搜尋-其他常用Query搜尋

一、字首搜尋

// 字首查詢
public void searchByPrefix(String field, String name, int number) {
    IndexSearcher indexSearcher = getIndexSearcher();
    try {
        Query query = new PrefixQuery(new Term(field, name));
        TopDocs topDocs = indexSearcher.search(query, number);
        System.out.println("一共查詢到:" + topDocs.totalHits);
        for (ScoreDoc scoreDoc : topDocs.scoreDocs) {
            Document document = indexSearcher.doc(scoreDoc.doc);
            System.out.println(document.get("id") + " " + document.get("name") + " " + document.get("email"));
        }
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        if (indexSearcher != null) {
            try {
                indexSearcher.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

二、萬用字元搜尋

// 萬用字元查詢
public void searchByWildcard(String field, String name, int number) {
    IndexSearcher indexSearcher = getIndexSearcher();
    try {
        // 在傳入的name中可以使用萬用字元,有?和*兩種,?表示匹配一個字元,*表示匹配任意多個字元
        Query query = new WildcardQuery(new Term(field, name));
        TopDocs topDocs = indexSearcher.search(query, number);
        System.out.println("一共查詢到:" + topDocs.totalHits);
        for (ScoreDoc scoreDoc : topDocs.scoreDocs) {
            Document document = indexSearcher.doc(scoreDoc.doc);
            System.out.println(document.get("id") + " " + document.get("name") + " " + document.get("email"));
        }
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        if (indexSearcher != null) {
            try {
                indexSearcher.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

三、布林查詢

可以使用布林查詢來組合查詢,使用MUST、SHOULD、MUST_NOT把要篩選的情況構造出來即可。

// 布林查詢
public void searchByBoolean(int number) {
    IndexSearcher indexSearcher = getIndexSearcher();
    try {
        BooleanQuery booleanQuery = new BooleanQuery();
        // MUST:必須出現;SHOULD:可以出現也可以不出現;MUST_NOT:不能出現
        booleanQuery.add(new TermQuery(new Term("name", "lisi")), BooleanClause.Occur.MUST);
        booleanQuery.add(new TermQuery(new Term("content", "content")), BooleanClause.Occur.SHOULD);
        booleanQuery.add(new TermQuery(new Term("email", "
[email protected]
")), BooleanClause.Occur.MUST_NOT); TopDocs topDocs = indexSearcher.search(booleanQuery, number); System.out.println("一共查詢到:" + topDocs.totalHits); for (ScoreDoc scoreDoc : topDocs.scoreDocs) { Document document = indexSearcher.doc(scoreDoc.doc); System.out.println(document.get("id") + " " + document.get("name") + " " + document.get("email")); } } catch (IOException e) { e.printStackTrace(); } finally { if (indexSearcher != null) { try { indexSearcher.close(); } catch (IOException e) { e.printStackTrace(); } } } }

四、短語查詢

關於這裡的setSlop(),多說兩句,slop是移動距離的意思,假如要查詢的內容是I like football,首先setSlop(1),再去add對content域查詢i和對content域查詢football,可以查詢出來,如果我將i和football的add順序顛倒一下,再次查詢,會發現沒有結果,此時,如果我將setSlop()的引數改為3,再去查詢,就會查到剛剛的資料,這是為什麼呢?

因為這個slop不是單純的指單詞間距,而是移動距離,對於新增順序是football i的情況,football右移1位,football和i重疊,右移2位,變成i football,右移3位,變成i * football,此時正好可以匹配上i like football。所以說setSlop()為3反而能查到是這個原因。如果我們setSlop(4)呢?經過查詢發現也能查到,也就是說我們set的這個slop是一個最大值,小於等於當前值的也包括在內。

另外,這個查詢需要對字元進行移動,對效能有一定的影響,所以要儘量使用。

最後一點,這個查詢不支援中文,因為查詢中的短語間距分詞是以空格作為標誌的,所以只能適用於英文查詢。

// 短語查詢
public void searchByPhrase(int number) {
    IndexSearcher indexSearcher = getIndexSearcher();
    try {
        PhraseQuery phraseQuery = new PhraseQuery();
        // 設定短語距離
        phraseQuery.setSlop(1);
        // 原文是“I like football”,但是這裡的I會被轉化為小寫,所以查詢的時候也是使用小寫
        phraseQuery.add(new Term("content","i"));
        phraseQuery.add(new Term("content","football"));
        TopDocs topDocs = indexSearcher.search(phraseQuery, number);
        System.out.println("一共查詢到:" + topDocs.totalHits);
        for (ScoreDoc scoreDoc : topDocs.scoreDocs) {
            Document document = indexSearcher.doc(scoreDoc.doc);
            System.out.println(document.get("id") + " " + document.get("name") + " " + document.get("email"));
        }
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        if (indexSearcher != null) {
            try {
                indexSearcher.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

五、模糊查詢

我們需要查詢lisi,但是我們輸入的是lixi,發現也可以查詢出來,這就是模糊查詢,它允許我們錯誤輸入某些字元,但是當我們改為bixi,發現就查不到了,說明模糊查詢允許我們輸入錯誤一個字元。我們可以通過建構函式來修改這個相似程度。簡單瞭解下即可,對中文的支援也不好。

// 模糊查詢
public void searchByFuzzy(int number) {
    IndexSearcher indexSearcher = getIndexSearcher();
    try {
        // FuzzyQuery(Term term, float minimumSimilarity, int prefixLength, int maxExpansions)
        // minimumSimilarity是最小相似度,取值範圍為0.0~1.0,包含0.0但不包含1.0,預設值為0.5
        // 當這個值越小,通過模糊查找出的文件的匹配程度就越低,文件的數量也就越多;當這個值越大,說明要匹配程度更大,匹配的文件數也就越少
        // 當相似度設定為1,那麼就退化為TermQuery查詢,所以當這個值>=1或<0會丟擲IllegalArgumentException異常
        // prefixLength是字首長度,預設為0,表示在進行模糊匹配的時候,要有多少個字首字母必須完全匹配
        Query query = new FuzzyQuery(new Term("name", "lixi"));
        TopDocs topDocs = indexSearcher.search(query, number);
        System.out.println("一共查詢到:" + topDocs.totalHits);
        for (ScoreDoc scoreDoc : topDocs.scoreDocs) {
            Document document = indexSearcher.doc(scoreDoc.doc);
            System.out.println(document.get("id") + " " + document.get("name") + " " + document.get("email"));
        }
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        if (indexSearcher != null) {
            try {
                indexSearcher.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}