5, 검색 (lucene 노트)
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
기본 도메인 포함
mike
mike john
、 mike OR john
기본 도메인 포함
mike
또는 john
+ mike + address:zhaotong
、 mike AND address:zhaotong
기본 도메인은
mike
인 동시에 address
인zhaotong
id:2
도메인 2id
、 address:Kunming – desc:she
address:Kunming AND NOT desc:she
네address
그리고 Kunming
네desc
의는 아니에요.she
기본 도메인은
(mike OR john) AND address:zhaotong
또는 mike
이며 john
는 address
zhaotong
desc:”she like”
도메인은 desc
she 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 버전 이후에 제공됩니다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.