Lucene 5学習ノート(3)-IndexReaderとよく使われる検索方法を再利用

28139 ワード

IndexReaderの使用の最適化
次のパターンは私たちがよく使うものです.インデックスの作成に対して、インデックスの検索は頻繁に使用されます.だからIndexReaderはよく使われるので、IndexReaderを単一のモードに設計すべきだと自然に考えています.しかし、インデックスが増加し、修正され、削除された後、IndexReaderはインデックス情報を再読み取りしなければならず、私たちのインデックス情報が正確であることを保証することができません.では、インデックスを再開くことなく、私たちのIndexReaderが最新のインデックスを読み取ることを保証することができますか?
あります.DirectoryReaderクラスの静的メソッドopenIfChangedを使用すれば目的を達成できます.この判断はインデックスが変更されたかどうかを判断し、変更された場合は、元のIndexReaderを解放します.次の例ではIndexReaderの使用手順を示します.
/**
 *        IndexReader
 * @return
 */
public IndexSearcher getSearcher() {
    try {
        if(reader==null) {
            reader = DirectoryReader.open(directory);
        } else {
            //    IndexReader    ,    DirectoryReader            IndexReader  
            //               
            //     :Lucene  -     (1)
            // http://blog.csdn.net/whuqin/article/details/42922813
            IndexReader tr = DirectoryReader.openIfChanged((DirectoryReader)reader);
            if(tr!=null) {
                reader.close();
                reader = tr;
            }
        }
        return new IndexSearcher(reader);
    } catch (CorruptIndexException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
    return null;
}

よく使われる検索方法
次に、一般的な検索方法をまとめ、最後に検索全体のテスト例を示し、参考にします.
1、TermQuery特定の項目を検索する(前節で説明した)
//       
Query query = new TermQuery(new Term(field,value));

2、TermRangeQuery特定範囲の項目を検索このQueryは数値範囲クエリーには適用されません.数値範囲クエリーはNumericRangeQueryで代用してください
Query query = new TermRangeQuery(field,new BytesRef(start.getBytes()),new BytesRef(end.getBytes()),true,true);

3、NumericRangeQuery数字範囲の項目を検索する
NumericRangeQuery<Integer> query = NumericRangeQuery.newIntRange(field,start,end,true,true);

4、PrefixQuery接頭辞照合検索
Query query = new PrefixQuery(new Term(field,value));

5、WildcardQueryワイルドカード検索
Query query = new WildcardQuery(new Term(field,value));

6、FuzzyQueryファジイマッチング検索ファジイマッチングとは、検索するキーワードが間違っていても、一定の範囲内で検索できることを意味する
FuzzyQuery query = new FuzzyQuery(new Term(field,value),maxEdits,prefixLength);

7、BooleanQuery複数条件のクエリ
BooleanQuery.Builder booleanQuery = new BooleanQuery.Builder();
Query query1 = new TermQuery(new Term(field1,value1));
Query query2 = new TermQuery(new Term(field2,value2));
booleanQuery.add(query1,BooleanClause.Occur.MUST);
booleanQuery.add(query2,BooleanClause.Occur.MUST);

8、PhraseQueryフレーズ検索
PhraseQuery phraseQuery = new PhraseQuery();
phraseQuery.setSlop(slop);
phraseQuery.add(new Term(field,value1));
phraseQuery.add(new Term(field,value2));

9、QueryParser方式のクエリー機能が最も強く、上のいくつかの方式のクエリーをほぼカバーしている.
Analyzer analyzer = new SimpleAnalyzer();
// QueryParser       1            
//     QueryParser    ,         (       2    )
// 【  】                       
QueryParser queryParser = new QueryParser(filedName,analyzer);
//              ,          
// queryParser.setAllowLeadingWildcard(true);
//           ,      AND
// parser.setDefaultOperator(Operator.AND);
Query query = queryParser.parse(el);

QueryParserコンストラクション関数の1番目のフィールドは、デフォルトの検索ドメインを表します.ここでelはクエリー式を表し、クエリー式の内容は非常に豊富で、クエリー式を通じて複雑なクエリー作業を完了します.たとえば、(1)「-name:mike+like」は、「一致するnameにはmikeはありませんがcontentにはlikeが必要です.+と-ドメインの説明の前に配置します」を表します.(2)「I like football」は、I like footballと完全に一致することを意味する.
クエリー式の詳細については、「Lucene実戦」を参照してください.
以下に、検索ツールクラス全体の使用方法を示します.
public class SearcherUtil {

    private String[] ids = {"1", "2", "3", "4", "5", "6"};
    private String[] names = {"liwei", "zhouguang", "liaoqunying", "yuanlian", "wudi", "huzhenyu"};
    private String[] emails = {"[email protected]", "[email protected]", "[email protected]", "[email protected]", "[email protected]", "[email protected]"};
    private String[] contents = {
            "I enjoy a folk song",
            "I come from Shanghai jiaotong university",
            "I am a university professor",
            "I am very cool",
            "I like football and I like basketball too",
            "I am a operations engineer"
    };
    //             
    private Date[] dates = null;
    //           
    private int[] attachs = {4, 0, 17, 4, 7, 3};


    private Directory directory;

    private IndexReader indexReader;

    private String indexDir = "C:\\dev\\lucene";


    private Map scores = new HashMap();

    /**
     *          
     */
    private void setDates() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        try {
            dates = new Date[ids.length];
            dates[0] = sdf.parse("1987-07-06");
            dates[1] = sdf.parse("1990-03-20");
            dates[2] = sdf.parse("1989-01-06");
            dates[3] = sdf.parse("1993-03-17");
            dates[4] = sdf.parse("1974-07-27");
            dates[5] = sdf.parse("1987-05-07");
        } catch (ParseException e) {
            e.printStackTrace();
        }
    }

    public SearcherUtil(){
        setDates();

        scores.put("163.com",2.0f);
        scores.put("qq.com", 1.5f);

        try {

            directory = FSDirectory.open(Paths.get(indexDir));
        } catch (IOException e) {
            e.printStackTrace();
        }

    }


    private IndexWriter getIndexWriter(){
        IndexWriter indexWriter = null;
        Analyzer analyzer = new SimpleAnalyzer();
        IndexWriterConfig iwc = new IndexWriterConfig(analyzer);
        try {
            indexWriter= new IndexWriter(directory,iwc);
        }catch (IOException e){
            e.printStackTrace();
        }
        return indexWriter;
    }


    /**
     *     
     */
    public void index() {
        IndexWriter writer = null;
        try {
            writer = getIndexWriter();
            writer.deleteAll();
            Document doc = null;
            for(int i=0;inew Document();
                doc.add(new StringField("id",ids[i], Field.Store.YES));
                StringField emailField = new StringField("email",emails[i],Field.Store.YES);

                String et = emails[i].substring(emails[i].lastIndexOf("@")+1);
                // System.out.println("email     => " + et);
                //             
                /*if(scores.containsKey(et)) {
                    emailField.setBoost(scores.get(et));
                } else {
                    emailField.setBoost(1.0f);
                }*/

                doc.add(emailField);
                doc.add(new TextField("content",contents[i],Field.Store.NO));
                doc.add(new StringField("name",names[i],Field.Store.YES));

                //     :        lucene(2)---lucene   Field    
                // http://blog.csdn.net/wuyinggui10000/article/details/45538155
                //      Field
                doc.add(new IntField("attach",attachs[i], Field.Store.YES));
                //      Field
                doc.add(new LongField("date",dates[i].getTime(), Field.Store.YES));
                writer.addDocument(doc);
            }
        } catch (CorruptIndexException e) {
            e.printStackTrace();
        } catch (LockObtainFailedException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if(writer!=null)writer.close();
            } catch (CorruptIndexException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }


    /**
     *    IndexSearcher
     *      IndexReader            ,       IndexReader      
     *                         
     *          ,     
     * @return
     */
    public IndexSearcher getIndexSearcher(){
        try {
            if(indexReader==null){
                indexReader = DirectoryReader.open(directory);
            }else {
                IndexReader newReader = DirectoryReader.openIfChanged((DirectoryReader) indexReader);
                if(newReader!=null){
                    //         IndexReader     
                    indexReader.close();
                    indexReader = newReader;
                }
            }
            IndexSearcher indexSearcher = new IndexSearcher(indexReader);
            return indexSearcher;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     *         ,     Directory   
     * @param directory
     * @return
     */
    public IndexSearcher getIndexSearcher(Directory directory){
        try {
            if(indexReader == null){
                indexReader = DirectoryReader.open(directory);
            }else {
                IndexReader newReader = DirectoryReader.openIfChanged((DirectoryReader)indexReader);
                indexReader.close();
                indexReader = newReader;
            }
            return new IndexSearcher(indexReader);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }


    public void searchByTerm(String field,String value,int num){
        //      IndexSearcher
        IndexSearcher searcher = getIndexSearcher();
        //       
        Query query = new TermQuery(new Term(field,value));
        try {
            TopDocs topDocs = searcher.search(query,num);
            System.out.println("          => " + topDocs.totalHits);
            Document document = null;
            for(ScoreDoc scoreDoc:topDocs.scoreDocs){
                document = searcher.doc(scoreDoc.doc);
                String result = "name => " + document.get("name") + "\t email => "+ document.get("email") +
                        "\t id => " + document.get("id") + "\t attach => " + document.get("attach") + "\t date => " + document.get("date");
                System.out.println(result);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            // IndexSearcher       
            IndexReader reader = searcher.getIndexReader();
            System.out.println("   reader      => " +  (reader == indexReader) );
        }
    }


    /**
     *
     * @param field
     * @param start
     * @param end
     * @param num
     */
    public void searchByTermRange(String field,String start,String end,int num){
        IndexSearcher searcher = getIndexSearcher();
        /**
         *    Query           ,          NumericRangeQuery   
         */
        Query query = new TermRangeQuery(field,new BytesRef(start.getBytes()),new BytesRef(end.getBytes()),true,true);
        showQueryResult(searcher,query,num);
    }

    /**
     *
     * @param field
     * @param start
     * @param end
     * @param num
     */
    public void searchByNumericRangeQuery(String field,Integer start,Integer end,int num){
        IndexSearcher searcher = getIndexSearcher();
        NumericRangeQuery query = NumericRangeQuery.newIntRange(field,start,end,true,true);
        showQueryResult(searcher,query,num);

    }

    /**
     *
     * @param searcher
     * @param query
     * @param num
     */
    private void showQueryResult(IndexSearcher searcher,Query query,Integer num){
        TopDocs topDocs = null;
        try {
            topDocs = searcher.search(query,num);
            System.out.println("          => " + topDocs.totalHits);
            Document document = null;
            for(ScoreDoc scoreDoc:topDocs.scoreDocs){
                document = searcher.doc(scoreDoc.doc);
                String result = "name => " + document.get("name") + "\t email => "+ document.get("email") +
                        "\t id => " + document.get("id") + "\t attach => " + document.get("attach") + "\t date => " + document.get("date");
                System.out.println(result);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     *       
     * @param field
     * @param value
     * @param num
     */
    public void searchByPrefix(String field,String value,int num){
        IndexSearcher searcher = getIndexSearcher();
        Query query = new PrefixQuery(new Term(field,value));
        showQueryResult(searcher,query,num);
    }

    /**
     *      
     *    : *           ,?         
     * @param field
     * @param value
     * @param num
     */
    public void searchByWildcard(String field,String value,int num){
        IndexSearcher searcher = getIndexSearcher();
        Query query = new WildcardQuery(new Term(field,value));
        showQueryResult(searcher,query,num);
    }

    /**
     *        
     * MUST       , “ ,  ”
     * SHOULD      ,     , “  ,  ”
     * @param field1
     * @param value1
     * @param field2
     * @param value2
     * @param num
     */
    public void searchByBoolean(String field1,String value1,String field2,String value2, int num){
        IndexSearcher searcher = getIndexSearcher();
        BooleanQuery.Builder booleanQuery = new BooleanQuery.Builder();
        Query query1 = new TermQuery(new Term(field1,value1));
        Query query2 = new TermQuery(new Term(field2,value2));
        booleanQuery.add(query1,BooleanClause.Occur.MUST);
        booleanQuery.add(query2,BooleanClause.Occur.MUST);
        showQueryResult(searcher,booleanQuery.build(),num);
    }


    /**
     *
     * slop       ,   ,           
     *                 
     *
     *     ,        ,      
     * @param field
     * @param value1
     * @param value2
     * @param num
     */
    public void searchByPrase(String field,String value1,String value2,int slop,int num){
        IndexSearcher searcher = getIndexSearcher();
        PhraseQuery phraseQuery = new PhraseQuery();
        phraseQuery.setSlop(slop);
        phraseQuery.add(new Term(field,value1));
        //   Term
        phraseQuery.add(new Term(field,value2));
        showQueryResult(searcher,phraseQuery,num);
    }


    /**
     *     
     * @param field
     * @param value
     * @param num
     */
    public void searchByFuzzy(String field,String value,int maxEdits, int prefixLength,int num){
        IndexSearcher searcher = getIndexSearcher();
        FuzzyQuery query = new FuzzyQuery(new Term(field,value),maxEdits,prefixLength);
        showQueryResult(searcher,query,num);
    }


    /**
     *        ,              
     *       QueryParser    
     * @param query
     * @param num
     */
    public void searchByQueryParser(Query query,int num){
        IndexSearcher searcher = getIndexSearcher();
        showQueryResult(searcher,query,num);
    }
}