4、IndexReaderとIndexWriterの宣言周期(luceneノート)

5597 ワード

一、説明
実際の開発では、IndexReaderIndexWriterの2つのオブジェクトを開くとリソースが消費されるため、データベースのセッションに対応する単一の例を使用するか、閉じずに1つのプールを使用するのが一般的です.
二、単例IndexReader
ここでは、コピーエンジニアリングlucene_index02lucene_index03であり、これまでのエンジニアリングに基づいて改善されています.
  • IndexUtil.javaクラスでIndexReaderのプロパティを宣言します:
  • private static IndexReader reader = null;//    IndexReader   
    
  • 次いで、方法IndexUtil():
  • を改良する.
    public IndexUtil() {
        try {
            setDates();//    
            scores.put("qq.com", 2.0f);//   "qq.com"           2.0,  :   1.0
            scores.put("sina.edu", 1.5f);
            directory = FSDirectory.open(new File("E:/myeclipse/Lucene/index"));
            reader = IndexReader.open(directory);//            IndexReader
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    

    構造法ではIndexReaderを実例化し,これにより単例の効果を達成した.
  • メソッド取得IndexSearcherクラスを定義する:
  • public IndexSearcher getSearcher(){
        return new IndexSearcher(reader);
    }
    
  • 検索方法の改善:
  •     public void search02(){
            IndexReader reader;
            try {
                IndexSearcher searcher = getSearcher();
                TermQuery query = new TermQuery(new Term("content", "like"));//       like 
                TopDocs tds = searcher.search(query, 10);
                for(ScoreDoc sd : tds.scoreDocs){
                    Document doc = searcher.doc(sd.doc);
                    //        getBoost()       1.0,            document,        。
                    //        ,    luke  
                    //                 
                    System.out.println("id :" + doc.get("id") 
                            + ",  :"+ doc.getBoost() 
                            + ",  :" + doc.get("name") 
                            + ",  :" + doc.get("email")
                            + ",    :" +doc.get("attach") 
                            + ",  :" + doc.get("date"));
                    searcher.close();//  :      reader,    searcher
                }
            } catch (CorruptIndexException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    

    注意:ここではreaderを閉じるのではなく、searcherを閉じます.そうすれば、readerはずっと1つ使用することができます.
  • テスト
  •     @Test
        public void testSearch02(){
            IndexUtil util = new IndexUtil();
            for(int i = 0; i < 5; i++){
                util.search02();//        5 
                try {
                    Thread.sleep(10000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    

    説明:ここでは、テスト時にインデックスを再生成し、上記のテスト方法を使用してテストします.私たちは10秒ごとに検索を実行します.検索の過程で、削除方法を実行し、idが1のインデックスを削除します.しかし、削除してもインデックスは少なくなりません.これは私たちがずっと同じreaderを使っているからです.しかし、このテストメソッドを閉じて、以前の検索メソッドtestSearch01を使用してテストすると、インデックスが1つ少なくなっていることがわかり、この問題について改善を続けます.
  • 改良getSearcher方法
  • public IndexSearcher getSearcher(){
        try {
            if(reader == null){
                reader = IndexReader.open(directory);
            }else{
                //  reader         reader,        reader
                IndexReader tr = IndexReader.openIfChanged(reader);
                if(tr != null){
                    reader.close();//    reader
                    reader = tr;
                }
            }
            return new IndexSearcher(reader);
        } catch (CorruptIndexException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
    

    説明:ここでは、openIfChangedを使用します.この方法は、readerが変化したときに新しいreaderに戻ります.そうしないと、古いreaderに戻ります.しかし、新しいreaderを生成した後、古いreaderを閉じる必要があります.その後、上記のテストメソッドを実行するときに削除メソッドを使用すると、インデックスがリアルタイムで更新されることがわかります.
    三、単例IndexWriter
    同様に、削除方法について説明します.
        public void delete(){
            IndexWriter writer = null;
            try {
                writer = new IndexWriter(directory, new IndexWriterConfig(Version.LUCENE_35, new StandardAnalyzer(Version.LUCENE_35)));
                
                //         ,     query,      term,term         
                //                   ,     numDocs  5 ,       ,  maxDoc  6 
                //                delete   。              ,      
                writer.deleteDocuments(new Term("id", "1"));//         1 id
                writer.commit();
            } catch (CorruptIndexException e) {
                e.printStackTrace();
            } catch (LockObtainFailedException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }/*finally{
                if(writer != null){
                    try {
                        writer.close();
                    } catch (CorruptIndexException e) {
                        e.printStackTrace();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }*/
        }
    

    ここではIndexWriterを閉じなくてもいいですが、このようにデータがリアルタイムで更新できない場合は、データベースのように提出すればいいです.
    最後に、ここでは単純に例を示しただけですが、例は完全ではありません.例えば、IndexReaderは構造関数でインスタンス化されています.単例ですが、インデックス作成方法のテスト時にもIndexReaderオブジェクトを作成しますが、最後には閉じません.この原因でオブジェクトの作成方法をテストするときに異常が発生したかどうかは不明ですが、後で解決します.
    具体的な一例実装については、http://www.cnblogs.com/likehua/archive/2012/02/20/2359087.htmlを参照してください.