본문 바로가기

Lucene

[lucene] TermFreqVector 얻기. (lucene 3.6, lucene 4.0)

루씬 3.X 버전까지는 IndexReader로부터 Term과 TermFreq를 얻기 위해서

아래와 같은 코드를 사용하였습니다.

package com.tistory.devyongsik.termFrequency;
import java.io.IOException;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.Field.Index;
import org.apache.lucene.document.Field.Store;
import org.apache.lucene.document.Field.TermVector;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.index.IndexWriterConfig.OpenMode;
import org.apache.lucene.index.TermFreqVector;
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 TestTermFrequency {
public static void main(String[] args) throws Exception, LockObtainFailedException, IOException {
String a = "learning perl learning java";
String b = "perl test learning";
Directory dir = new RAMDirectory();
Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_36); //문서 내용을 분석 할 때 사용 될 Analyzer
IndexWriterConfig iwc = new IndexWriterConfig(Version.LUCENE_36, analyzer);
iwc.setOpenMode(OpenMode.CREATE);
IndexWriter writer = new IndexWriter(dir, iwc); //8. 드디어 IndexWriter를 생성합니다.
Document doc1 = new Document();
Field f1 = new Field("f", a, Store.NO, Index.ANALYZED, TermVector.YES);
doc1.add(f1);
Document doc2 = new Document();
Field f2 = new Field("f", b, Store.NO, Index.ANALYZED, TermVector.YES);
doc2.add(f2);
writer.addDocument(doc1);
writer.addDocument(doc2);
writer.commit();
writer.close();
IndexReader ir = IndexReader.open(dir);
TermFreqVector termFreqVector1 = ir.getTermFreqVector(0, "f");
TermFreqVector termFreqVector2 = ir.getTermFreqVector(1, "f");
String[] terms1 = termFreqVector1.getTerms();
int[] freqs1 = termFreqVector1.getTermFrequencies();
for(int i = 0; i < terms1.length; i++) {
System.out.println(terms1[i] + " : " + freqs1[i]);
}
String[] terms2 = termFreqVector2.getTerms();
int[] freqs2 = termFreqVector2.getTermFrequencies();
for(int i = 0; i < terms2.length; i++) {
System.out.println(terms2[i] + " : " + freqs2[i]);
}
}
}
view raw gistfile1.java hosted with ❤ by GitHub




IndexReader로부터 

TermFreqVector termFreqVector1 = ir.getTermFreqVector(0, "f"); 와 같은 형태로

document 하나에 대한 TermFreqVector를 얻어내고

이를 통해서 term 배열과 freq 배열을 얻어서 조합하는 방식입니다.


4.0에서는 IndexReader.getTermFreqVector 메서드가 사라지고 대신 아래와 같은 방법을 사용합니다.

package com.tistory.devyongsik.analyzer.termFrequency;
import java.io.IOException;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.FieldType;
import org.apache.lucene.index.DocsEnum;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.index.FieldInfo.IndexOptions;
import org.apache.lucene.index.IndexWriterConfig.OpenMode;
import org.apache.lucene.index.Terms;
import org.apache.lucene.index.TermsEnum;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.LockObtainFailedException;
import org.apache.lucene.store.RAMDirectory;
import org.apache.lucene.util.BytesRef;
import org.apache.lucene.util.Version;
public class TestTermFrequency {
public static void main(String[] args) throws Exception, LockObtainFailedException, IOException {
String a = "learning perl learning java learning ruby";
String b = "perl test t";
Directory dir = new RAMDirectory();
Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_42); //문서 내용을 분석 할 때 사용 될 Analyzer
IndexWriterConfig iwc = new IndexWriterConfig(Version.LUCENE_42, analyzer);
iwc.setOpenMode(OpenMode.CREATE);
IndexWriter writer = new IndexWriter(dir, iwc); //8. 드디어 IndexWriter를 생성합니다.
Document doc1 = new Document();
FieldType f1type = new FieldType();
f1type.setIndexed(true);
f1type.setStored(false);
f1type.setTokenized(true);
f1type.setStoreTermVectors(true);
f1type.setIndexOptions(IndexOptions.DOCS_AND_FREQS_AND_POSITIONS_AND_OFFSETS);
Field f1 = new Field("f", a, f1type);
doc1.add(f1);
Document doc2 = new Document();
Field f2 = new Field("f", b, f1type);
doc2.add(f2);
writer.addDocument(doc1);
writer.addDocument(doc2);
writer.commit();
writer.close();
IndexReader ir = IndexReader.open(dir);
Terms terms1 = ir.getTermVector(0, "f");
Terms terms2 = ir.getTermVector(1, "f");
System.out.println(terms1.getDocCount());
System.out.println(terms1.getSumDocFreq());
System.out.println(terms1.getSumTotalTermFreq());
TermsEnum termsEnum1 = terms1.iterator(null);
//termsEnum1.seekExact(new BytesRef("java"), true);
//System.out.println("GDGDG : " + termsEnum1.totalTermFreq());
BytesRef term1 = null;
while((term1 = termsEnum1.next()) != null) {
System.out.println("1 : " + termsEnum1.term().utf8ToString() + " : " + termsEnum1.docFreq() + " : " + termsEnum1.totalTermFreq());
}
TermsEnum termsEnum2 = terms2.iterator(null);
BytesRef term2 = null;
while((term2 = termsEnum2.next()) != null) {
System.out.println("2 : " + termsEnum2.term().utf8ToString() + " : " + termsEnum2.docFreq() + " : " + termsEnum2.totalTermFreq());
}
}
}
view raw gistfile1.java hosted with ❤ by GitHub


IndexReader.getTermVector(0, "f") 메서드를 사용합니다.

이때 Terms라는 클래스의 인스턴스를 얻을 수 있는데, 위 코드의 예에서는 doucment 0번에 대한

인스턴스이므로 하나의 document (위의 예에서는 document 0)가 색인된 역인덱스 파일의 통계 정보를

가지고 있는 것과 같은 값을 가지고 있습니다.


예를 들어서, termEnum.docFreq()는 해당 term을 가진 전체 document의 개수이지만, 위의 경우 전체 document가

하나인것과 같은 상태이므로 1을 return하는 형태입니다.


전체 Terms에 대한 통계정보가 아직 제대로 수집이 되지 않는 부분이 있습니다만 (http://devyongsik.tistory.com/577) 곧 수정이 된다고 합니다.


그리고, Terms도 하나의 document가 아니라

전체 혹은 특정 Term이나 필드에 대한 Terms 인스턴스를 얻어내서 그에 대한

통계를 얻을 수 있는 방법도 있을 것 같습니다.