5, 검색 (lucene 노트)

31774 단어
이전에 색인 생성에 대한 기본 설명을 드렸습니다. 다음은 검색과 관련된 방법(공정lucene_searcher01을 보겠습니다.
1. 정확한 색소TermQuery
여기에 우리는 관련 코드를 제시하고 싶다: SearcherUtil.java
package cn.itcast.searcher;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
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.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.index.Term;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.NumericRangeQuery;
import org.apache.lucene.search.PrefixQuery;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TermQuery;
import org.apache.lucene.search.TermRangeQuery;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.search.WildcardQuery;
import org.apache.lucene.search.BooleanClause.Occur;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.LockObtainFailedException;
import org.apache.lucene.store.RAMDirectory;
import org.apache.lucene.util.Version;

public class SearcherUtil {
    private Directory directory;
    private IndexReader reader;
    private String[] ids = { "1", "2", "3", "4", "5", "6" };
    private String[] emails = { "[email protected]", "[email protected]", "[email protected]",
            "[email protected]", "[email protected]", "[email protected]" };
    private String[] content = { "welcom to visited the space,I like football",
            "hello boy, i like someone", "come on baby", "first blood",
            "I like football,I like football",
            "my girlfriend is so beatiful, every body like game" };
    private int[] attaches = { 2, 5, 6, 5, 8, 4 };
    private String[] names = { "tom", "jack", "goudan", "alibaba", "jerry", "kitty" };
    private Date[] dates = null;
    private Map scores = new HashMap();//     Map,      

    public SearcherUtil(){
        directory = new RAMDirectory();
        setDates();
        index();
    }
    
    public IndexSearcher getSearcher(){
        try {
            if (reader == null) {
                reader = IndexReader.open(directory);
            }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 searchByTerm(String field, String name, int num){
        IndexSearcher searcher = getSearcher();
        Query query = new TermQuery(new Term(field, name));
        try {
            TopDocs tds = searcher.search(query, num);//TopDocs         ScoreDoc    
            System.out.println("     : " + tds.totalHits);
            for(ScoreDoc sd : tds.scoreDocs){//ScoreDoc   TopDocs            
                Document doc = searcher.doc(sd.doc);
                System.out.println("id :" + doc.get("id") 
                                + ",  :"+ doc.getBoost() 
                                + ",  :" + doc.get("name") 
                                + ",  :" + doc.get("email")
                                + ",    :" +doc.get("attach") 
                                + ",  :" + doc.get("date"));
            }
            
            searcher.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    public void index() {
        IndexWriter writer = null;
        try {
            writer = new IndexWriter(directory, new IndexWriterConfig(
                    Version.LUCENE_35, new StandardAnalyzer(Version.LUCENE_35)));
            //            
            writer.deleteAll();
            Document document = null;
            for (int i = 0; i < ids.length; i++) {
                document = new Document();
                // id    ,     、  ,email     ,      ,        
                //     ,          ,     。       ,        
                //                ,    
                document.add(new Field("id", ids[i], Field.Store.YES,
                        Field.Index.NOT_ANALYZED_NO_NORMS));
                document.add(new Field("email", emails[i], Field.Store.YES,
                        Field.Index.NOT_ANALYZED));
                document.add(new Field("content", content[i], Field.Store.NO,
                        Field.Index.ANALYZED));
                document.add(new Field("name", names[i], Field.Store.YES,
                        Field.Index.NOT_ANALYZED_NO_NORMS));

                //        ,        true      
                document.add(new NumericField("attach", Field.Store.YES, true)
                        .setIntValue(attaches[i]));
                //        
                document.add(new NumericField("date", Field.Store.YES, true)
                        .setLongValue(dates[i].getTime()));

                String et = emails[i].substring(emails[i].lastIndexOf("@") + 1);
                //     
                if (scores.containsKey(et)) {
                    document.setBoost(scores.get(et));
                } else {
                    document.setBoost(0.5f);
                }
                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();
                }
            }
        }
    }
    
    //     
    private void setDates() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        try {
            dates = new Date[ids.length];
            dates[0] = sdf.parse("2015-02-15");
            dates[1] = sdf.parse("2015-03-01");
            dates[2] = sdf.parse("2015-05-18");
            dates[3] = sdf.parse("2015-09-05");
            dates[4] = sdf.parse("2015-12-15");
            dates[5] = sdf.parse("2015-08-29");
        } catch (ParseException e) {
            e.printStackTrace();
        }
    }
}
TestSearch.java
package cn.lucene.test;
import org.junit.Before;
import org.junit.Test;
import cn.itcast.searcher.SearcherUtil;

public class TestSearch {
    
    private SearcherUtil util;
    
    @Before
    public void init(){
        util = new SearcherUtil();
    }
    
    @Test
    public void searchByTerm(){
        //util.searchByTerm("name", "Jack", 3);
        util.searchByTerm("content", "like", 3);//  :                       
    }
}

설명: 여기에서 우리는 인덱스를 메모리에 저장하기 때문에 프로그램이 실행되고 나면 없어지기 때문에 이전의 클래스를 사용해서 인덱스를 만들 수 없습니다. 여기에서 우리는 인덱스를 만드는 방법을 이 클래스에 쓸 것입니다. 여기서 우리는
Query query = new TermQuery(new Term(field, name));

정확한 검색을 수행합니다.주의: 조회된 총 기록 수는 우리가 표시하고자 하는 기록 수와 관계가 없습니다.
2. 범위 조회TermRangeQuery
public void searchByTermRang(String field, String start, String end, int num){
    IndexSearcher searcher = getSearcher();
    //                      ,      true  false   ?      
    Query query = new TermRangeQuery(field, start, end, true, true);
    try {
        TopDocs tds = searcher.search(query, num);
        System.out.println("     : " + tds.totalHits);
        for(ScoreDoc sd : tds.scoreDocs){
            Document doc = searcher.doc(sd.doc);
            System.out.println("id :" + doc.get("id") 
                    + ",  :"+ doc.getBoost() 
                    + ",  :" + doc.get("name") 
                    + ",  :" + doc.get("email")
                    + ",    :" +doc.get("attach") 
                    + ",  :" + doc.get("date"));
        }
        
        searcher.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

테스트:
@Test
public void searchByTermRang(){
    //util.searchByTermRang("id", "1", "3", 10);
    //util.searchByTermRang("attach", "1", "3", 10);      
    util.searchByTermRang("name", "a", "j", 10);//  :          
}

설명: 여기는 범위 조회입니다.
Query query = new TermRangeQuery(field, start, end, true, true);

조회를 진행하고 관련 구역과 범위 구간을 제시하면 된다.하지만 이곳의 구간은 시험할 때 효과가 없는지 모른다.그러나 이런 범위 조회는 숫자에 대해 무효다.
3. 디지털 범위 조회 NumericRangeQuery
public void searchByNumricRange(String field, int start, int end, int num){
    IndexSearcher searcher = getSearcher();
    //         ,               
    Query query = NumericRangeQuery.newIntRange(field, start, end, true, true);
    try {
        TopDocs tds = searcher.search(query, num);
        System.out.println("     : " + tds.totalHits);
        for(ScoreDoc sd : tds.scoreDocs){
            Document doc = searcher.doc(sd.doc);
            System.out.println("id :" + doc.get("id") 
                    + ",  :"+ doc.getBoost() 
                    + ",  :" + doc.get("name") 
                    + ",  :" + doc.get("email")
                    + ",    :" +doc.get("attach") 
                    + ",  :" + doc.get("date"));
        }
        
        searcher.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

테스트:
@Test
public void searchByNumricRange(){
    util.searchByNumricRange("attach", 2, 3, 10);
}

설명
Query query = NumericRangeQuery.newIntRange(field, start, end, true, true);

조회를 진행하다.
4. 접두사 검색PrefixQuery
public void searchByPrefix(String field, String value, int num){
    IndexSearcher searcher = getSearcher();
    Query query = new PrefixQuery(new Term(field, value));//value        
    try {
        TopDocs tds = searcher.search(query, num);
        System.out.println("     : " + tds.totalHits);
        for(ScoreDoc sd : tds.scoreDocs){
            Document doc = searcher.doc(sd.doc);
            System.out.println("id :" + doc.get("id") 
                    + ",  :"+ doc.getBoost() 
                    + ",  :" + doc.get("name") 
                    + ",  :" + doc.get("email")
                    + ",    :" +doc.get("attach") 
                    + ",  :" + doc.get("date"));
        }
        
        searcher.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

테스트:
@Test
public void searchByPrefix(){
    //util.searchByPrefix("name", "j", 10);
    util.searchByPrefix("content", "s", 10);
}

설명
Query query = new PrefixQuery(new Term(field, value));

그중value이 접두사 값이다.
5. 와일드카드 검색 WildcardQuery
public void searchByWildCard(String field, String value, int num){
    IndexSearcher searcher = getSearcher();
    Query query = new WildcardQuery(new Term(field, value));
    try {
        TopDocs tds = searcher.search(query, num);
        System.out.println("     : " + tds.totalHits);
        for(ScoreDoc sd : tds.scoreDocs){
            Document doc = searcher.doc(sd.doc);
            System.out.println("id :" + doc.get("id") 
                    + ",  :"+ doc.getBoost() 
                    + ",  :" + doc.get("name") 
                    + ",  :" + doc.get("email")
                    + ",    :" +doc.get("attach") 
                    + ",  :" + doc.get("date"));
        }
        
        searcher.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

테스트:
@Test
public void searchByWildCard(){
    //*      ,?      
    //util.searchByWildCard("name", "j?", 10);//    
    util.searchByWildCard("name", "j*", 10);
}

설명
Query query = new WildcardQuery(new Term(field, value));

그 중에서 우리는 ?를 사용하여 임의의 문자를 표시하고 *호를 사용하여 임의의 문자를 표시한다.
6. 다중 조건 쿼리 BooleanQuery
public void searchByBoolean(int num){
    IndexSearcher searcher = getSearcher();
    BooleanQuery query = new BooleanQuery();
    //          tom      like   
    query.add(new TermQuery(new Term("name", "tom")), Occur.MUST);//            ,   MUST_NOT      
    query.add(new TermQuery(new Term("content", "like")), Occur.MUST);//   SHOULD      
    try {
        TopDocs tds = searcher.search(query, num);
        System.out.println("     : " + tds.totalHits);
        for(ScoreDoc sd : tds.scoreDocs){
            Document doc = searcher.doc(sd.doc);
            System.out.println("id :" + doc.get("id") 
                    + ",  :"+ doc.getBoost() 
                    + ",  :" + doc.get("name") 
                    + ",  :" + doc.get("email")
                    + ",    :" +doc.get("attach") 
                    + ",  :" + doc.get("date"));
        }
        
        searcher.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

테스트:
@Test
public void searchByBoolean(){
    util.searchByBoolean(10);
}

설명
BooleanQuery query = new BooleanQuery();
//          tom      like   
query.add(new TermQuery(new Term("name", "tom")), Occur.MUST);
query.add(new TermQuery(new Term("content", "like")), Occur.MUST);

여기Occur.MUST는 있어야 한다는 뜻, Occur.MUST_NOT는 없어야 한다는 뜻, Occur.SHOULD는 있어도 되고 없어도 된다는 뜻이다.이렇게 해서 우리는 여러 조건을 조합하기 시작했다.
7. 구문 검색PhraseQuery
    public void searchByPhrase(int num){
        IndexSearcher searcher = getSearcher();
        PhraseQuery query = new PhraseQuery();
        //  I like football,    I football        (  ),        
        query.setSlop(1);
        query.add(new Term("content", "i"));//  :         ,           
        query.add(new Term("content", "football"));
        try {
            TopDocs tds = searcher.search(query, num);
            System.out.println("     : " + tds.totalHits);
            for(ScoreDoc sd : tds.scoreDocs){
                Document doc = searcher.doc(sd.doc);
                System.out.println("id :" + doc.get("id") 
                        + ",  :"+ doc.getBoost() 
                        + ",  :" + doc.get("name") 
                        + ",  :" + doc.get("email")
                        + ",    :" +doc.get("attach") 
                        + ",  :" + doc.get("date"));
            }
            
            searcher.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

테스트:
@Test
public void searchByPhrase(){
    util.searchByPhrase(10);
}

설명
PhraseQuery query = new PhraseQuery();
query.setSlop(1);
query.add(new Term("content", "i"));
query.add(new Term("content", "football"));

여기에서 우리는 값을 줄 때 소문자를 주어야 하지만, 소문자와 크기가 일치하는 인덱스를 모두 조회할 것이다.물론 이런 조회는 자원을 소모하는 동시에 중국어 검색에 큰 역할을 하지 않는다.
8. 모호한 조회FuzzyQuery
    public void searchByFuzzy(int num){
        IndexSearcher searcher = getSearcher();
        //             ,       ,               ,       (   ) 0.5<=1,   2
        FuzzyQuery query = new FuzzyQuery(new Term("name", "tome"), 0.5f, 2);
        try {
            TopDocs tds = searcher.search(query, num);
            System.out.println("     : " + tds.totalHits);
            for(ScoreDoc sd : tds.scoreDocs){
                Document doc = searcher.doc(sd.doc);
                System.out.println("id :" + doc.get("id") 
                        + ",  :"+ doc.getBoost() 
                        + ",  :" + doc.get("name") 
                        + ",  :" + doc.get("email")
                        + ",    :" +doc.get("attach") 
                        + ",  :" + doc.get("date"));
            }
            
            searcher.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

테스트:
@Test
public void searchByFuzzy(){
    util.searchByFuzzy(10);
}

설명
FuzzyQuery query = new FuzzyQuery(new Term("name", "tome"), 0.5f, 2);

검색을 진행하면 모호한 검색과 어댑터 검색이 다르기 때문에 오류 검색으로 이해할 수 있습니다. 만약에 뒤에 두 개의 파라미터를 주지 않으면 기본적으로 한 문자의 오류를 허용할 수 있습니다. 물론 이것은 뒤에 두 개의 파라미터를 사용하여 설정할 수 있습니다.밑에서 두 번째 매개 변수는 일치력입니다. 이 값은 1.0보다 작고 기본값은 1.0입니다.값이 작을수록 일치가 작아지고, 마지막 매개 변수는 오류가 발생할 수 있는 문자 수를 표시합니다.이 방법은 많이 쓰지 않으니 이해하면 된다.
9.QueryParser
public void searchByQueryParser(Query query, int num){
    IndexSearcher searcher = getSearcher();
    try {
        TopDocs tds = searcher.search(query, num);
        System.out.println("     : " + tds.totalHits);
        for(ScoreDoc sd : tds.scoreDocs){
            Document doc = searcher.doc(sd.doc);
            System.out.println("id :" + doc.get("id") 
                    + ",  :"+ doc.getBoost() 
                    + ",  :" + doc.get("name") 
                    + ",  :" + doc.get("email")
                    + ",    :" +doc.get("attach") 
                    + ",  :" + doc.get("date"));
        }
        
        searcher.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

테스트:
@Test
public void searchByQueryParser() throws ParseException{
    //1、  QueryParser  ,      content
    QueryParser parser = new QueryParser(Version.LUCENE_35, "content", new StandardAnalyzer(Version.LUCENE_35));
    parser.setDefaultOperator(Operator.AND);//         ,           
    parser.setAllowLeadingWildcard(true);//           ,    ,    
    //  content   like 
    Query query = parser.parse("like");//          
    //query = parser.parse("I football");//      I  football 
    query = parser.parse("I AND football");//      I   football 
    
    //      name tom 
    query = parser.parse("name:like");
    query = parser.parse("name:j*");
    query = parser.parse("email:*@sina.com");//      ,      ,      
    //       like    football,      ,         
    query = parser.parse("- name:tom + football");
    query = parser.parse("id:[1 TO 3]");//      ,TO     
    query = parser.parse("id:{1 TO 3}");//      ,       
    query = parser.parse("\"I like football\"");//    "I like football"
    query = parser.parse("\"I football\"~1");//  I football          
    util.searchByQueryParser(query, 10);
}

설명: 이렇게 하면 우리가 전송한 매개 변수를 처리한 후에 조회를 진행합니다. 우선 우리는 QueryParser 대상을 구성합니다. 이 대상의 두 번째 매개 변수(이곳은 content)는 기본 검색의 영역이 당연히 바뀔 수 있음을 나타냅니다.우리가 사용하면
query = parser.parse("I  football");

검색을 진행할 때 중간 빈칸을 '또는', 즉 "I" 또는 "football" 색인이 있는 것으로 기본값으로 합니다. 물론 저희는
parser.setDefaultOperator(Operator.AND);

기본 '또는' 을 '와' 으로 설정하면 조회에 이미 "I" 색인도 있고 "football" 색인도 있다는 것을 의미합니다. 물론 우리는 일반적으로 바꾸지 않고 "AND" 를 사용하여 조건 '과' 조작을 합니다.여기에 있는 어댑터 조회는 효율이 비교적 낮기 때문에 기본적으로 수위에 두는 것을 허용하지 않는다. 물론 우리는 사용할 수 있다
parser.setAllowLeadingWildcard(true);

허락을 받다.조회할 수 있는 조합은 아직 많이 있다. 다음은 다음과 같다.
컨디션
속뜻mike
기본 도메인 포함mikemike johnmike OR john
기본 도메인 포함mike 또는 john+ mike + address:zhaotongmike AND address:zhaotong
기본 도메인은 mike인 동시에 addresszhaotong id:2도메인 2idaddress:Kunming – desc:she address:Kunming AND NOT desc:sheaddress그리고 Kunmingdesc의는 아니에요.she
기본 도메인은 (mike OR john) AND address:zhaotong 또는 mike 이며 johnaddresszhaotong desc:”she like” 도메인은 descshe like
기본 도메인은 j*로 시작합니다.j
모호한 검색johe~johe id:[1 TO 3] 1-3
페이지 검색
페이지 조회를 할 때 우리는 많은 파일을 필요로 한다. 그렇지 않으면 효과를 볼 수 없다.여기에는 경로id에 파일이 준비되어 있습니다. 파일이 충분하지 않으면 다음과 같은 방법으로 복사할 수 있습니다. E:/myeclipse/Lucene/somefile/
@Test
public void testCopuFiles(){
    File file = new File("E:/myeclipse/Lucene/somefile/");
    for(File f : file.listFiles()){
        String destFileName = FilenameUtils.getFullPath(f.getAbsolutePath()) 
                + FilenameUtils.getBaseName(f.getName()) + ".py";
        try {
            FileUtils.copyFile(f, new File(destFileName));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

물론 이 방법에는 의존 패키지TestSearch.java가 필요하다.이후에 우리는 이전의 인덱스 생성 방법을 사용할 수 없습니다. 왜냐하면 이전에 만든 인덱스는 메모리에 저장되어 있기 때문에, 여기에 우리는 하드디스크에 저장해야 합니다.그래서 우리는 색인을 만드는 클래스를 제시했는데 사실 이전에 우리는 이미 썼다. 여기는 복습으로 쓰인다. commons-io.jar
package cn.itcast.searcher;
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() / 1024)));
                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();
                }
            }
        }
    }
}

다음은 페이지 조회 방법을 보겠습니다. 물론 여기서 우리는 페이지 조회를 사용하지 않는 방법을 비교로 제시합니다.
//     
public void searchPage(String query, int pageIndex, int pageSize) {
    try {
        Directory dir = FileIndexUtil.getDirectory();
        IndexSearcher searcher = getSearcher(dir);
        QueryParser parser = new QueryParser(Version.LUCENE_35, "content",
                new StandardAnalyzer(Version.LUCENE_35));

        Query q = parser.parse(query);
        TopDocs tds = searcher.search(q, 100);//TopDocs         ScoreDoc    
        ScoreDoc[] sds = tds.scoreDocs;//ScoreDoc   TopDocs            
        int start = (pageIndex - 1) * pageSize;
        int end = pageIndex * pageSize;
        for(int i = start; i < end; i++ ){
            Document doc = searcher.doc(sds[i].doc);
            System.out.println("id :" + sds[i].doc + ",  :" + doc.get("path") + ",  :" + doc.get("filename"));
        }
        searcher.close();
    } catch (org.apache.lucene.queryParser.ParseException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } 
}
//       
public void searchNoPage(String query) {
    try {
        Directory dir = FileIndexUtil.getDirectory();
        IndexSearcher searcher = getSearcher(dir);
        QueryParser parser = new QueryParser(Version.LUCENE_35, "content",
                new StandardAnalyzer(Version.LUCENE_35));
        Query q = parser.parse(query);
        TopDocs tds = searcher.search(q, 100);//TopDocs         ScoreDoc    
        ScoreDoc[] sds = tds.scoreDocs;//ScoreDoc   TopDocs            
        for(int i = 0; i < sds.length; i++ ){
            Document doc = searcher.doc(sds[i].doc);
            System.out.println("id :" + sds[i].doc + ",  :" + doc.get("path") + ",  :" + doc.get("filename"));
        }
        searcher.close();
    } catch (org.apache.lucene.queryParser.ParseException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

테스트:
@Test
public void searchPage01(){
    util.searchPage("java", 1, 10);
    System.out.println("*****************");
    util.searchPage("java", 2, 10);
    System.out.println("*****************");
    util.searchNoPage("java");
}

여기서 우리는 결과에서 페이지 조회의 효과를 볼 수 있다.그러나 페이지 조회지만 매번 주어진 조회 항목의 색인을 모두 조회해 내는 효율이 낮다.다음은 두 번째 페이지 나누기 조회 방식을 보겠습니다.
public void searchPageByAfter(String query, int pageIndex, int pageSize){
    try {
        Directory dir = FileIndexUtil.getDirectory();
        IndexSearcher searcher = getSearcher(dir);
        QueryParser parser = new QueryParser(Version.LUCENE_35, "content",
                new StandardAnalyzer(Version.LUCENE_35));

        Query q = parser.parse(query);
        TopDocs tds = searcher.search(q, 100);//TopDocs         ScoreDoc    
        ScoreDoc[] sds = tds.scoreDocs;//ScoreDoc   TopDocs            
        
        int last = (pageIndex - 1) * pageSize - 1;
        tds = searcher.searchAfter(sds[last], q, 10);//          
        for(ScoreDoc sd : tds.scoreDocs){
            Document doc = searcher.doc(sd.doc);
            System.out.println("id :" + sd.doc + ",  :" + doc.get("path") + ",  :" + doc.get("filename"));
        }
        searcher.close();
    } catch (org.apache.lucene.queryParser.ParseException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

여기
int last = (pageIndex - 1) * pageSize - 1;
tds = searcher.searchAfter(sds[last], q, 10);//          

이전 페이지의 마지막 색인을 나타내는 다음 색인이 표시됩니다.테스트 방법은 여기에서 생략했습니다. 이전과 유사합니다.그러나 우리는 우리가 제시한 조회 항목의 수가 여전히 100개라는 것을 보았다. 즉, 우리는 여전히 100개의 데이터를 조회해냈다(100개의 데이터가 있다면). 이렇게 하면 사실상 첫 번째 페이지 조회와 효율적으로 차이가 크지 않다.향상된 기능은 다음과 같습니다.
private ScoreDoc getLaScoreDoc(int pageIndex, int pageSize, Query query, IndexSearcher searcher) throws IOException{
    if(pageIndex == 1){
        return null;
    }
    //       mysql        pageSize   ,      pageSize ,    2*pageSize ,    
    int num = pageSize * (pageIndex - 1);
    TopDocs tds = searcher.search(query, num);
    return tds.scoreDocs[num - 1];
}

public void searchPageByAfter01(String query, int pageIndex, int pageSize){
    try {
        Directory dir = FileIndexUtil.getDirectory();
        IndexSearcher searcher = getSearcher(dir);
        QueryParser parser = new QueryParser(Version.LUCENE_35, "content",
                new StandardAnalyzer(Version.LUCENE_35));

        Query q = parser.parse(query);
        ScoreDoc lastSd = getLaScoreDoc(pageIndex, pageSize, q, searcher);
        TopDocs tds = searcher.searchAfter(lastSd, q, pageSize);
        ScoreDoc[] sds = tds.scoreDocs;//ScoreDoc   TopDocs            
        
        for(ScoreDoc sd : tds.scoreDocs){
            Document doc = searcher.doc(sd.doc);
            System.out.println("id :" + sd.doc + ",  :" + doc.get("path") + ",  :" + doc.get("filename"));
        }
        searcher.close();
    } catch (org.apache.lucene.queryParser.ParseException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

설명: 페이지에 표시되는 줄 수와 표시할 페이지 번호를 통해 표시되는 시작 위치의 인덱스와 표시할 총 줄 수를 계산합니다(방법FileIndexUtil.java.여기에 주의하십시오. 만약에 우리가 10을 표시하고 페이지 번호가 2를 표시한다면, 표시할 데이터의 첫 번째는 10이고, 여기의 getLaScoreDoc는 19입니다.데이터베이스처럼 주어진 개수만 조회할 수 없기 때문에 주어진 모든 개수만 조회해야 한다. 이렇게 하면 많든 적든 일정한 효율을 높일 수 있다.물론 이 방법은 3.5 버전 이후에 제공됩니다.

좋은 웹페이지 즐겨찾기