본문 바로가기

Lucene

[lucene] TopDocCollector와 TopFieldDocs.

루씬에서 색인을 한 후 검색을 수행 할 때

ScoreDoc 객체를 얻어올 수 있는 두가지 방법이 있습니다.

하나는 TopDocCollector를 사용하는 것이고 또 하나는

TopFieldDocs를 사용하는 것입니다.

일단 두개의 사용 샘플 코드를 살펴보면

TopDocCollector collector = new TopDocCollector(5 * hitsPerPage);
    QueryParser parser = new QueryParser(fieldName, analyzer);
    query = parser.parse("keyword");
 
    searcher.search(query, collector);
    ScoreDoc[] hits = collector.topDocs().scoreDocs;
   Document doc = searcher.doc(hits[i].doc);


그리고

Sort sort = new Sort(fieldName,true);
QueryParser parser = new QueryParser(fieldName, analyzer);
query = parser.parse("keyword");
TopFieldDocs tfd = searcher.search(query,null,50,sort);
 
ScoreDoc[] hits = tfd.scoreDocs;
Document doc = searcher.doc(hits[i].doc);

입니다. 가장 큰 차이점은 Sort 의 사용 여부입니다.

TopDocCollector는 지정된 갯수만큼만 루씬에서 검색시에 계산된 유사도 점수를 가지고

상위 Document를 가져 올 수 있습니다.

아래 예제 에서는 Sort를 위해서 일단 검색된 모든 Document를 대상으로 해당 필드를

Sorting하는 작업이 들어가게 됩니다.

즉, 50개만 가져오려고 하더라도 전체 검색된 문서 갯수가 3000개라면 TopDocCollector는

그냥 순서대로 50개만 가져오면 되지만, TopFieldDocs는 3000개를 Sort하고자 하는

필드를 기준으로 Sorting을 하는 점이 다른 부분입니다.

class TopDocCollector extends HitCollector

TopDocCollector는 HitCollector를 상속하고 있습니다.

searcher.search(query, collector); 는 최종적으로는

search(Weight weight, Filter filter, HitCollector results) 이 메소드로 전달되어 실행되게 됩니다.

내부적으로 Query를 가지고 Weight를 만들고 필터등등을 붙여서 호출하게 되겠지요.

그리고 TopFieldDocs tfd = searcher.search(query,null,50,sort); 에서

search 메서드는 내부적으로 TopFieldDocCollector를 생성하여 그것을

search(weight, filter, collector); 메서드로 넘겨주게 됩니다. 바로 위에 적어놓은

search(Weight weight, Filter filter, HitCollector results) 입니다.

짐작하시겠지만 TopFieldDocCollector는 TopDocCollector를 상속하고 있습니다.

그래서 위와 같은 사용이 가능하겠지요..


내부적으로 들어가보지는 못 했지만 아마 Collector가 내부적으로 collect()라는 메서드가 있는데

이녀석이 sort를 하던 상위 스코어 Document만 가져오던 알아서 자기 일을 하는 것 같습니다.


루씬 메일링 리스트에 질문을 해봐도 위 두개의 가장 큰 차이점은 Sort라고 하네요..

Sort의 사용법은 SortField를 이용하는 방법도 있지만 그건 나중에..다시..^^;

그리고 그 sort의 과정에서 해당 필드의 term을 모두 캐싱 하기 때문에

out of memory가 발생 할 수 있습니다.