본문 바로가기

Lucene

[lucene] TermFreqVector, TermPositionVector

루씬 인 액션을 보던 중 텀벡터에 대한 얘기가 나와서 살펴보았다.

간단하게 색인을 해 놓고..

소스를 간단하게 만들어서 돌려보았다..

package kr.co.gshs.lucene.test;

import java.io.IOException;

import org.apache.lucene.document.Document;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.TermFreqVector;
import org.apache.lucene.index.TermPositionVector;
import org.apache.lucene.index.TermVectorOffsetInfo;

public class TermVectorTest {

public static void main(String[] args) throws IOException {
  IndexReader reader = IndexReader.open("D:/lucene_data/test_index");
  int maxDoc = reader.maxDoc();

  System.out.println("maxDoc = " + maxDoc);

  for(int i = 0; i < maxDoc && i < 10; i++) {
   //System.out.println("i");
   Document doc = reader.document(i);
   String subject = doc.get("TITLE");

   System.out.println("title = " + subject);

   TermFreqVector termFreqVector = reader.getTermFreqVector(i, "TITLE");
   TermPositionVector termPosition = (TermPositionVector)reader.getTermFreqVector(i, "TITLE");

   String[] terms = termFreqVector.getTerms();
   int[] freqs = termFreqVector.getTermFrequencies();

   String[] termsPo = termPosition.getTerms();
   int[] termPo = termPosition.getTermFrequencies();

   //System.out.println("termPo = ["+termPo.length+"]");

   for(int j = 0; j < terms.length; j++) {
    System.out.println("TERM = " + terms[j] + "["+freqs[j]+"]");
   }

   for(int k = 0; k < termPo.length; k++) {
    System.out.println("TERMs = " + termsPo[k] + "["+termPo[k]+"]");
    TermVectorOffsetInfo[] offsets = termPosition.getOffsets(k);
    int[] tp = termPosition.getTermPositions(k);

    for(int kk = 0; kk < tp.length; kk++) {
     System.out.println("term position : " + tp[kk]);
    }

    for(int cp = 0; cp <offsets.length; cp++) {
     System.out.println("start_off_set : " + offsets[cp].getStartOffset());
     System.out.println("end_off_set : " + offsets[cp].getEndOffset());
    }
   }

  }

 }

}

일단 검정 부분만 보면...
IndexReader로 부터 getTermFreqVector 메서드를 통해 TermFreqVector 를 생성하여

getTerms()와 getTermFrequencies()를 사용하여 TITLE 필드에 있는 컨텐츠의

텀과 빈도수를 가져오고 있다.

실제로 색인되어 있는대로 가져오기 때문에 제목이 만약에

"테스트 테스트 테스트"라면 이 넘은

terms[0] = 테스트
freqs[0] = 3
이 된다. 만약 동의어에 의해서 "테스트 입니다" 라는 제목이

"테스트 test 입니다" 라고 색인이 되어 있다고 한다면 (물론 offset이나 position은

테스트와 test가 동일하게 색인)

terms = {테스트, test, 입니다}
freqs = {1, 1, 1} 이 된다.

참고로 이 메서드를 사용하기 위해서는 색인시

Field field = new Field(...., Field.TermVector.YES) 를 주어야 한다.

이제 파랑 부분을 보자.

TermPositionVector termPosition = (TermPositionVector)reader.getTermFreqVector(i, "TITLE");

다운 캐스팅을 통해서 TermPositionVector 를 가져오고 있다.

이 부분을 실행시 만약 색인 할 때
Field.TermVector.WITH_POSITIONS_OFFSETS 이나 WITH_POSITION 조건을 주지 않으면 , ClassCastException이 발생한다.

위 조건을 주어 색인을 하고 TermPositionVector를 가지고 와서

위 for문을 돌리면 아래와 같은 결과가 나온다.

title = Siebel주문Interface항목

TERMs = interface[1]
term position : 2
start_off_set : 8
end_off_set : 17

TERMs = siebel[1]
term position : 0
start_off_set : 0
end_off_set : 6

TERMs = 주문[1]
term position : 1
start_off_set : 6
end_off_set : 8

TERMs = 항목[1]
term position : 3
start_off_set : 17
end_off_set : 19

TermFreqVector 처럼 term와 Freq도 가져올 수 있고
색인되어 있는 정보를 사용하여 텀의 position과 offset을 가져올 수도 있다.

다만..이 정보를 포함해서 색인할때의 속도라던가...그런 것들은 비교를 하지 못 했고..
이걸 어디에 쓰는게 가장 효과적일까...하는 생각이 들기도 한다.;;

여기저기 찾아보니
TermPositionVector는 Highlight 클래스에서 사용하는 것 같다.

색인에 정보가 있으면 TermPositionVector를 가져와서 하이라이트 할 부분을 찾아내고

없으면 Analyzer를 통해 다시 tokenStream을 뽑아내서 찾아내는 방식이 아닐까...

하는 생각이 든다.


그거 말고 어디 또 좋은데 쓸 수 있을것 같은데...;;;