8、搜索排序和搜索过滤(lucene笔记)

一、搜索排序(工程lucene_analyzer03

这里我们使用之前工程中创建索引的一个工具类```FileIndexUtil.java

package cn.itcast.util;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.NumericField;
import org.apache.lucene.index.CorruptIndexException;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.store.LockObtainFailedException;
import org.apache.lucene.util.Version;

public class FileIndexUtil {

    private static Directory directory = null;
    static {
        try {
            directory = FSDirectory.open(new File(
                    "E:/myeclipse/Lucene/index"));

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static Directory getDirectory() {
        return directory;
    }

    // 创建索引
    public static void index(boolean hasNew) {
        IndexWriter writer = null;
        try {
            writer = new IndexWriter(directory, new IndexWriterConfig(
                    Version.LUCENE_35, new StandardAnalyzer(Version.LUCENE_35)));
            if (hasNew) {
                writer.deleteAll();//如果我们要新建索引,那么将之前创建的删除
            }
            File file = new File("E:/myeclipse/Lucene/somefile");

            Document document = null;
            for (File f : file.listFiles()) {
                document = new Document();
                document.add(new Field("content", new FileReader(f)));
                document.add(new Field("filename", f.getName(),
                        Field.Store.YES, Field.Index.NOT_ANALYZED));
                document.add(new Field("path", f.getAbsolutePath(),
                        Field.Store.YES, Field.Index.NOT_ANALYZED));
                document.add(new NumericField("date", Field.Store.YES, true)
                        .setLongValue(f.lastModified()));
                // 最后我们将字节数转换成kb
                document.add(new NumericField("size", Field.Store.YES, true)
                        .setIntValue((int) (f.length())));
                writer.addDocument(document);
            }
        } 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();
                }
            }
        }
    }
}

说明:此类是之前我们写的一个创建索引的类。下面再写一个类用于测试排序的类SearchTest.java

package cn.lucene.test;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.index.CorruptIndexException;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.queryParser.ParseException;
import org.apache.lucene.queryParser.QueryParser;
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.util.Version;
import cn.itcast.util.FileIndexUtil;

public class SearchTest {

    private static IndexReader reader;
    static {
        try {
            reader = IndexReader.open(FileIndexUtil.getDirectory());
        } catch (CorruptIndexException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public IndexSearcher getSearcher() {
        try {
            if (reader == null) {
                reader = IndexReader.open(FileIndexUtil.getDirectory());
            } else {
                IndexReader tr = IndexReader.openIfChanged(reader);
                if (tr != null) {
                    reader.close();
                    reader = tr;
                }
            }
            return new IndexSearcher(reader);
        } catch (CorruptIndexException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    public void searcher(String queryStr, Sort sort) {
        try {
            IndexSearcher searcher = getSearcher();
            QueryParser parser = new QueryParser(Version.LUCENE_35, "content",
                    new StandardAnalyzer(Version.LUCENE_35));
            Query query = parser.parse(queryStr);
            TopDocs tds = null;
            if (sort != null) {
                tds = searcher.search(query, 50, sort);
            } else {
                tds = searcher.search(query, 50);
            }
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            for (ScoreDoc sd : tds.scoreDocs) {
                Document doc = searcher.doc(sd.doc);
                System.out.println("id:" + sd.doc + ",评分:" + sd.score + ",名称:"
                        + doc.get("filename") + ",路径:" + doc.get("path")
                        + ",文件大小:" + doc.get("size") + ",日期:"
                        + sdf.format(new Date(Long.valueOf(doc.get("date")))));
            }
            searcher.close();
        } catch (ParseException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

相关的代码我们在之前已经讲过,下面我们进行排序测试TestAnalyzer.java

package cn.lucene.test;
import org.apache.lucene.search.Sort;
import org.apache.lucene.search.SortField;
import org.junit.Before;
import org.junit.Test;
import cn.itcast.util.FileIndexUtil;

public class TestAnalyzer {
    private SearchTest st;
    
    @Before
    public void init(){
        st = new SearchTest();
    }
    
    //重新创建索引
    @Test
    public void Index(){
        FileIndexUtil.index(true);
    }
    
    @Test
    public void test01(){
        //只要设置了排序,那么评分就没有了
        //st.searcher("java", Sort.INDEXORDER);//以序号排序
        //st.searcher("java", Sort.RELEVANCE);//通过评分排序
        
        //st.searcher("java", new Sort(new SortField("size", SortField.INT)));//通过文件大小排序
        //st.searcher("java", new Sort(new SortField("date", SortField.LONG)));//通过日期排序
        //st.searcher("java", new Sort(new SortField("filename", SortField.STRING)));//通过文件名排序,升序
        //st.searcher("java", new Sort(new SortField("filename", SortField.STRING, true)));//通过文件名排序,降序
        //先按大小排序,再按评分排序
        st.searcher("java", new Sort(new SortField("size", SortField.INT), SortField.FIELD_SCORE));
    }
}

说明:通过上面的测试代码我们可以看到,lucene默认有很多排序的规则,只要我们自行设置好便可达到相关排序的目的,当然在后面我们还需要自定义排序规则来达到我们的要求,这里只是入门。

二、搜索过滤

这里我们说三个进行搜索过滤的过滤器,其实前面已经提到,这里作为复习.
SearchTest.java

    public void searcher(String queryStr, Filter filter){
        try {
            IndexSearcher searcher = getSearcher();
            QueryParser parser = new QueryParser(Version.LUCENE_35, "content",
                    new StandardAnalyzer(Version.LUCENE_35));
            Query query = parser.parse(queryStr);
            TopDocs tds = null;
            if (filter != null) {
                //这里我们使用过滤器
                tds = searcher.search(query, filter, 50);
            } else {
                tds = searcher.search(query, 50);
            }
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            for (ScoreDoc sd : tds.scoreDocs) {
                Document doc = searcher.doc(sd.doc);
                System.out.println("id:" + sd.doc + ",评分:" + sd.score + ",名称:"
                        + doc.get("filename") + ",路径:" + doc.get("path")
                        + ",文件大小:" + doc.get("size") + ",日期:"
                        + sdf.format(new Date(Long.valueOf(doc.get("date")))));
            }
            searcher.close();
        } catch (ParseException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

说明:在这个方法中我们传入的不是排序类,而是过滤器。下面进行测试。

    @Test
    public void test02(){
        //范围搜索,从json.c到json.php的分为内搜索json,最后两个参数表示是前后都是闭区间
        Filter tr = new TermRangeFilter("filename", "json.c", "json.php", true, true);
        //大小范围搜索
        tr = NumericRangeFilter.newIntRange("size", 10, 100, true, true);
        //可以通过一个query进行过滤
        tr = new QueryWrapperFilter(new WildcardQuery(new Term("filename", "*.c")));
        st.searcher("json", tr);
    }

说明:这里我们给出了三个过滤器,分别进行名字范围、发笑范围过滤器和一个可以通过Query进行过滤去过滤器。

你可能感兴趣的:(8、搜索排序和搜索过滤(lucene笔记))