org.jhlabs.scany.engine.search.LuceneSearcher.java Source code

Java tutorial

Introduction

Here is the source code for org.jhlabs.scany.engine.search.LuceneSearcher.java

Source

/*******************************************************************************
 * Copyright (c) 2008 Jeong Ju Ho.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the GNU Public License v2.0
 * which accompanies this distribution, and is available at
 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
 * 
 * Contributors:
 *     Jeong Ju Ho - initial API and implementation
 ******************************************************************************/
package org.jhlabs.scany.engine.search;

import java.io.IOException;
import java.util.Iterator;
import java.util.List;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.queryParser.ParseException;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.Sort;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.search.TopFieldDocs;
import org.apache.lucene.store.Directory;
import org.jhlabs.scany.engine.entity.Record;
import org.jhlabs.scany.engine.entity.RecordList;
import org.jhlabs.scany.engine.entity.Relation;
import org.jhlabs.scany.engine.index.RecordKeyException;
import org.jhlabs.scany.engine.search.extract.PagingRecordExtractor;
import org.jhlabs.scany.engine.search.extract.RandomRecordExtractor;
import org.jhlabs.scany.engine.search.extract.RecordExtractor;
import org.jhlabs.scany.engine.search.extract.SequentialRecordExtractor;
import org.jhlabs.scany.engine.search.paging.IterablePaging;
import org.jhlabs.scany.engine.search.query.LuceneQueryBuilder;
import org.jhlabs.scany.engine.search.query.QueryBuilderException;

/**
 * .
 * 
 * + ? 
 *      ? ?  ?  ?  .
 * 
 * + ? 
 *     ?  ? ?    ,
 *     ?   ??  ? ?    ?  .
 *     
 * +  ?
 *      ? ? ? ?   .
 *        ?      ??? .
 *     ()? ? ?? ?? ?? ? ?? ?  ??  .
 *      ? ?  ? ??? ? ?? ? ? ? . 
 * 
 * <p>Created: 2007. 01. 19  1:29:18</p>
 * 
 * @author Gulendol
 *
 */
public class LuceneSearcher extends SearchModel implements AnySearcher {

    /**
     * ??
     * @param relation 
     * @throws ScanySearchException
     */
    public LuceneSearcher(Relation relation) throws AnySearcherException {
        super(relation);
    }

    /**
     * ?? ? ? .
     * ? ?    1 ? . 
     * @param queryText
     * @return
     * @throws AnySearcherException
     */
    public RecordList search(String queryText) throws AnySearcherException {
        return search(queryText, 1);
    }

    /**
     * ?? ? ? .
     *   ?  .
     * @param queryText
     * @return
     * @throws AnySearcherException
     */
    public RecordList search(int pageNo) throws AnySearcherException {
        return search(null, pageNo);
    }

    /**
     * ?? ? ? .
     *  ?? , ?   ?    null? .
     *    Record[0]? .
     * ? () ??   null? ,
     *   ,  ?  ??    ?. 
     * @param queryText ?  ?
     * @param pageNo ? 
     * @return hitsPerPage  ?? Record .
     * @throws AnySearcherException
     */
    public RecordList search(String queryText, int page) throws AnySearcherException {
        if (page <= 0)
            return null;

        try {
            setQueryText(queryText);
            setPage(page);

            RecordExtractor recordExtractor = new PagingRecordExtractor((SearchModel) this);

            search((SearchModel) this, recordExtractor);

            return recordExtractor.getRecordList();

        } catch (Exception e) {
            throw new AnySearcherException("Search failed.", e);
        }
    }

    /**
     *   ? ?  .
     *     ?  .
     *      ?  .
     * @return hitsPerPage ? 
     * @throws AnySearcherException
     */
    public RecordList random() throws AnySearcherException {
        return random(null);
    }

    /**
     *   ? ?  .
     *      ? ?  .
     *      ?  .
     * ? () ??   null? ,
     *   ,  ?  ??    ?. 
     * @param queryText ?
     * @return hitsPerPage ? 
     * @throws AnySearcherException
     */
    public RecordList random(String queryText) throws AnySearcherException {
        try {
            setQueryText(queryText);

            RecordExtractor recordExtractor = new RandomRecordExtractor((SearchModel) this);

            search((SearchModel) this, recordExtractor);

            return recordExtractor.getRecordList();

        } catch (Exception e) {
            throw new AnySearcherException("Random search failed.", e);
        }
    }

    /**
     * (Record) ??  ? ? ? ? ?   ?  . 
     * ()? ? ? ?? ??? ?   ?  . 
     * ? () ??   null? ,
     *   ,  ?  ??    ?. 
     * @param start  ?
     * @param maxRecords  
     * @param reverse  
     * @return
     * @throws AnySearcherException
     */
    public RecordList seek(int start, int maxRecords, boolean reverse) throws AnySearcherException {
        if (start < 0)
            return null;

        try {
            setPage(1);
            setStartRecord(start);
            setHitsPerPage(maxRecords);
            setReverse(reverse);

            RecordExtractor recordExtractor = new SequentialRecordExtractor((SearchModel) this);

            search((SearchModel) this, recordExtractor);

            return recordExtractor.getRecordList();

        } catch (Exception e) {
            throw new AnySearcherException("Sequential search failed.", e);
        }
    }

    public Iterator<Record> interator(int numHitsToCollect) throws AnySearcherException {
        return interator(null, numHitsToCollect);
    }

    public Iterator<Record> interator(String queryText, int numHitsToCollect) throws AnySearcherException {
        try {
            setQueryText(queryText);

            Analyzer analyzer;

            if (getRelation().getPerFieldAnalyzer() != null)
                analyzer = getRelation().getPerFieldAnalyzer();
            else
                analyzer = getRelation().getAnalyzer();

            LuceneQueryBuilder queryBuilder = new LuceneQueryBuilder();
            queryBuilder.addQuery(getFilterAttributeList());
            queryBuilder.addQuery(getParsedQueryText(), getQueryAttributeList(), analyzer);

            Query query = queryBuilder.build();

            IterablePaging iter = new IterablePaging((SearchModel) this, query, numHitsToCollect);
            iter.skipTo(getStartRecord());
            iter.gather(getHitsPerPage());

            return iter.iterator();
        } catch (Exception e) {
            throw new AnySearcherException("search failed.", e);
        }
    }

    public static RecordList search(SearchModel searchModel, RecordExtractor recordExtractor)
            throws QueryBuilderException, RecordKeyException, IOException, ParseException {
        IndexSearcher indexSearcher = null;

        try {
            Directory directory = searchModel.getRelation().openDirectory();
            indexSearcher = new IndexSearcher(directory);

            Analyzer analyzer;

            if (searchModel.getRelation().getPerFieldAnalyzer() != null)
                analyzer = searchModel.getRelation().getPerFieldAnalyzer();
            else
                analyzer = searchModel.getRelation().getAnalyzer();

            LuceneQueryBuilder queryBuilder = new LuceneQueryBuilder();
            queryBuilder.addQuery(searchModel.getFilterAttributeList());
            queryBuilder.addQuery(searchModel.getParsedQueryText(), searchModel.getQueryAttributeList(), analyzer);

            Query query = queryBuilder.build();
            query = indexSearcher.rewrite(query);

            List<SortAttribute> sortAttributeList = searchModel.getSortAttributeList();
            Sort sort = null;

            if (sortAttributeList != null && sortAttributeList.size() > 0)
                sort = SearchModelUtils.makeSort(searchModel.getSortAttributeList());

            ScoreDoc[] docs = null;

            if (sort == null) {
                TopDocs topDocs = indexSearcher.search(query, searchModel.getHitsPerPage());
                docs = topDocs.scoreDocs;
                searchModel.setTotalRecords(topDocs.totalHits);
            } else {
                TopFieldDocs topFieldDocs = indexSearcher.search(query, searchModel.getHitsPerPage(), sort);
                docs = topFieldDocs.scoreDocs;
                searchModel.setTotalRecords(topFieldDocs.totalHits);
            }

            recordExtractor.extract(indexSearcher.getIndexReader(), docs);

            return recordExtractor.getRecordList();

        } finally {
            try {
                if (indexSearcher != null)
                    indexSearcher.close();
            } catch (Exception e2) {
                e2.printStackTrace();
            }
        }
    }
}