官术网_书友最值得收藏!

3.3.1 查詢過程

Lucene中使用IndexSearcher類對索引進行檢索。IndexSearcher類繼承自抽象類Searcher。查詢依賴一個或者多個索引庫,IndexSearcher依賴一個或者多個IndexReader。查詢執行過程如圖3-9所示。

圖3-9 查詢執行過程

在初始化一個IndexSearcher類時,重要的就是要告訴它使用哪個索引完成查找任務??梢杂肐ndexReader初始化一個IndexSearcher對象。

        Directory directory = FSDirectory.open(new
        File("E:/luceneTest/fileindex"));
        IndexReader indexReader = DirectoryReader.open(directory);
        IndexSearcher indexSearcher = new IndexSearcher(indexReader);

DirectoryReader是IndexReader的子類。使用DirectoryReader.open(directory)方法得到IndexReader的實例。

Directory類型的對象包含索引存放的路徑信息,從而可以定位索引。這里使用Directory類型的對象來創建IndexReader,然后再用IndexReader構建IndexSearcher。要查詢的索引往往只有一個,所以也可以直接使用Directory類型的對象來構建IndexSearcher。

        String indexDir = "D:/indexdir"; //索引庫路徑
        Directory directory = FSDirectory.open(new File(indexDir)); //打開一個文件路徑
        //只讀的方式使用directory,所以read-only=true
        IndexSearcher searcher = new IndexSearcher(directory, true); //隱式創建了
        //IndexReader

上面只是一個隱式創建IndexReader的簡單寫法。使用Directory構造的IndexSearcher實例仍然各自持有一個IndexReader實例,若系統中存在同一個索引的多個IndexSearcher實例時,會占用過多的內存空間。這時,應該是一份索引用一個IndexReader實例打開,用IndexReader構造IndexSearcher實例。

可以用DirectoryReader.getVersion()取得版本號:

        System.out.println("版本號 :"+reader.getVersion());

DirectoryReader類是IndexReader的子類。

把111.doc分成111,1111.doc分成1111,11111.doc分成11111。這樣輸入111,就只能搜索到111.doc。一段有意義的文字需要通過Analyzer分割成一個個詞語后才能按關鍵詞搜索。Analyzer就是分析器,StandardAnalyzer是Lucene中最常用的分析器。

        Analyzer analyzer = new StandardAnalyzer();

為了達到更好的搜索效果,不同的語言可以使用不同的分析器,例如CnAnalyzer就是一個主要處理中文的分析器。

Analyzer返回的結果就是一串Token。Token包含一個代表詞本身含義的字符串和該詞在文章中相應的起止偏移位置,Token還包含一個用來存儲詞類型的字符串。

Term是搜索語法的最小單位,復雜的搜索語法會分解成一個個的Term查詢,它表示文檔中的一個詞語。Term由兩部分組成:它表示的詞語和這個詞語所出現的Field。例如:

        new Term("url", "http://www.lietu.com");

最簡單的Query對象是TermQuery。根據TermQuery查詢索引庫。

        Query query = new TermQuery(new Term("url", "http://www.lietu.com"));
        //搜索索引庫并且返回最相關的10個文檔
        TopDocs tds = searcher.search(query, 10);

要是用戶輸入一個逗號,也會搜出文檔來,逗號是停用詞。一般停用詞進索引,但是搜索的時候會過濾掉。指用戶輸入逗號,系統識別為停用詞就給提示說它不能進行搜索。

查詢串中可能包括一些高級查詢語法,例如,要查找包含java的PDF文件,可以使用查詢串“java filetype:pdf”。所以用查詢分析器QueryParser來解析查詢串,也就是根據查詢串生成Query對象。例如:

        Analyzer analyzer = new StandardAnalyzer();
        QueryParser qp = new QueryParser(fields, analyzer);
        query = qp.parse(queryString);

使用IndexSearcher的search()方法執行搜索,返回一個TopDocs對象。TopDocs對象中的totalHits屬性記錄搜索返回結果的總條數?;镜年P鍵詞查詢代碼如下:

        String indexDir = "D:/indexdir"; //索引庫路徑
        Directory directory = FSDirectory.open(new File(indexDir)); //打開一個文件路徑
        // read-only=true
        IndexSearcher searcher = new IndexSearcher(directory, true); //搜索


        String defaultField = "title"; //默認查詢列
        String queryString ="NBA"; //查詢詞
        Analyzer analyzer = new StandardAnalyzer();
        QueryParser parser = new QueryParser(defaultField,
                                            analyzer);


        Query query = parser.parse(queryString);
        TopDocs docs = searcher.search(query, 10);  //查詢最多只返回前10條結果

這里的FSDirectory表示硬盤中的索引,RAMDirectory表示內存中的索引,可以用來測試索引和查找過程。

遍歷查詢結果:

        ScoreDoc[] hits = docs.scoreDocs; //從TopDocs取得查詢結果


        // 遍歷結果
        for (ScoreDoc hit : hits){
            Document hitDoc = searcher.doc(hit.doc);
            System.out.println(hitDoc.get("title") +hit.score); //輸出標題和文檔相關度分值
        }

ScoreDoc中的score屬性就是相關度。相關度得分是1~0的值。1表示相關度最高,而0則表示不相關。文檔的相關度跟很多因素有關。比如字段的長短、里面詞條的權重等。決定score的因素簡單概括如下:

(1) 項頻率,即查詢項在某個文檔中出現的次數;

(2) 文檔頻率,即查詢項在很多文檔中出現的次數。

完整的查詢代碼:

        Directory directory = FSDirectory.open(new File("d:/testindex"));
        // DirectoryReader讀入一個目錄下的索引文件
        IndexReader ir = DirectoryReader.open(directory);
        //打開索引庫
        IndexSearcher searcher = new IndexSearcher(ir);


        //根據查詢詞搜索索引庫
        TopDocs docs = searcher.search(new TermQuery(new Term("title", "text")), 10);
        //遍歷查詢結果
        ScoreDoc[] hits = docs.scoreDocs;
        for (ScoreDoc hit : hits){
            System.out.print("doc:"+hit.doc+" score:"+hit.score+"\n");
        }
        //關閉索引庫
        ir.close();
主站蜘蛛池模板: 横峰县| 通化市| 鹤峰县| 乳源| 会同县| 临沧市| 环江| 宁德市| 宁城县| 桐城市| 昆明市| 河间市| 凤翔县| 石林| 哈密市| 房产| 阿鲁科尔沁旗| 阜城县| 喀喇| 乃东县| 桂林市| 溧水县| 日照市| 沁水县| 敦化市| 图们市| 莒南县| 固安县| 冕宁县| 红桥区| 涡阳县| 镇巴县| 晋中市| 中超| 万年县| 临沂市| 苏尼特左旗| 桑植县| 麻阳| 泸定县| 平度市|