목요일, 4월 18
Shadow

#021 색인 필드 설정

Field클래스는 색인에 문서를 추가할 때 가장 핵심이 되는 클래스 중 하나이다. Field인스턴스를 생성할 때 색인 할 작업과 설정도 지정한다. 설정은 기능에 따라 구분해 소개하며, 색인 관련 설정, 저장 관련 설정, 텀백터 관련 설정 등의 순서로 설명한다.
1. 색인 관련 설정

Field.Index.ANALYZED

필드에 지정된 텍스트를 분석기에 넘겨 일련의 토큰을 뽑아 내 각 토큰을 검색할수 있게 한다. 일반적인 텍스트 필드에서 사용하기 좋다. 

Field.Index.NOT_ANALYZED

필드에 지정된 텍스트를 검색하게 역파일 색인에 추가하긴 하지만, 분석기로 텍스트를 처리하지는 않는다. 즉 텍스트 전체를 스트링으로 만든다. 

Field.ANALYZED_NO_NORMS

norm값을 색인에 저장하지 않는다. norm값은 색인할 때 지정했던 중요도를 색인에 보관하지만 검색할때 메모리를 조금더 사용한다. 

Field.NOT_ANALYZED_NO_NORMS

norm값을 색인에 저장하지 않는다 색인이 차지하는 용량과 검색 시점의 메모리 사용량을 절약하고자 할때 사용한다. 토큰을 하나만 갖고 있는 필드에 중요도를 지정하지 않는한 norm값이 필요하지 않는다. 

위 Field 클래스는 루씬 3대에서 사용하였으며, 현재 4~5대 버전에서는 변경되었다.

1. BinaryDocValuesField: BytesRef 값을 저장한다.
2. DoubleDocValuesField: NumericDocValues로 double형의 시멘틱 슈거 값을 저장한다. 
3. DoubleField: 필터나 정렬의 범위 효과를 위한 double 인덱스 필드를 저장한다. 
4. FloatDocValuesField: NumericDocValues float형 시멘틱 슈거 값을 저장한다.
5. FloatField: 필터나 정렬의 범위 효과를 위한 float 인덱스 필드를 저장한다. 
6. IntField: 필터나 정렬의 범위 효과를 위한 int 인덱스 필드를 저장한다.  
7. LongField: 필터나 정렬의 범위 효과를 위한 long 인덱스 필드를 저장한다. 
8. NumericDocValuesField: 필터나 정렬범위 지정을 위한 long형의 각각의 도큐먼트를 저장한다. 
9. SortedDocValuesField: 필터나 정렬범위 지정을 위한 BytesRef형의 각각의 도큐먼트를 저장한다. 
10. SortedNumericDocValuesField: 스코어링과 정렬을 위한 각각의 필드를 저장한다.
11. SortedSetDocValuesField: BytesRefd의 패싯, 그룹, 조인을 위한 인덱스를 저장한다. 
12. StoredField: IndexSearch.doc, IndexReader.document의 저장된 값을 리턴한다. 
13. StringField: 토크나이저로 나누지 않고 인덱싱한다. 
14. TextField: 텀 벡터를 뺀 토크나이저로 나누어 인덱싱 한다. 

2. 필드의 원문 저장 관련 설정
필드의 본문을 저장하는 설정을 사용하면 색인 시점에 필드에 추가했던 그대로의 텍스트 원문을 색인안에 저장할 것인지 선택할 수 있으며, 텍스트를 색인에 저장해두면 검색결과로 받아온 문서에서 원래 텍스트를 그대로 받아올수 있다.

2-1 Store.YES
필드의 텍스트를 색인에 그대로 저장한다. 색인에 텍스트를 저장하면 필드에 추가한 텍스트를 그대로 색인에 저장하며, 나중에 IndexReader를 통해 다시 그대로 받아올수 있다.

2-2 Store.NO
필드의 텍스트를 색인에 저장하지 않는다. Store.No설정은 주로 Index.ANALAYZED와 함께 사용하며, 필드의 내용을 검색해야 하긴 하지만 내용이 길고 굳이 나중에 결과 화면에 보여줄 필요가 없는 내용인 경우에 사용한다.

3. 텀 벡터 관련 설정
간혹 문서를 색인 할 때 나중에 검색 시점에 개별 텀을 모두 가져와야 할 필요가 있다고 생각할 때가 있다. 예를 들어 저장된 필드의 내용을 하이라이팅 할때 속도를 크게 개선할 수 있다. 사용자가 버튼을 눌렀을때 해당 문서에서 가장 주요하다고 판단되는 텀을 기준으로 비슷한 문서를 찾아 볼수 있다.
5.4버전에서는 Dprecated되어 더이상 사용을 하지않는다.

4. 문서와 필드의 중요도
필드와 문서마다 서로 중요도가 다른 경우가 있고, 중요도를 지정해 각 문서와 필드가 얼마나 중요한지를 표현할 수 있다.
색인할때 지정하는 중요도 값을 변경하려면 해당 문서를 삭제하고 다시 색인해야 한다.
index time boost관련 필드가 setBoost에서 NumericDocValuesField로 변경되었다.
참고로 루씬이 연관도 점수를 계산하는 방법 때문에 필드에 담겨있는 텍스트의 길이가 짧을수록 자연적으로 중요도가 높아지는 경향이 있다.

package foo.bar;

import org.apache.lucene.analysis.core.WhitespaceAnalyzer;
import org.apache.lucene.document.*;
import org.apache.lucene.index.*;
import org.apache.lucene.queries.CustomScoreQuery;
import org.apache.lucene.queries.function.FunctionQuery;
import org.apache.lucene.queries.function.valuesource.LongFieldSource;
import org.apache.lucene.queryparser.classic.MultiFieldQueryParser;
import org.apache.lucene.queryparser.classic.ParseException;
import org.apache.lucene.queryparser.classic.QueryParser;
import org.apache.lucene.search.*;
import org.apache.lucene.store.RAMDirectory;

import java.io.IOException;

public class HelloApp {
    public static void main(String[] args) throws IOException, ParseException {
        RAMDirectory ramDirectory = new RAMDirectory();
        IndexWriter indexWriter = new IndexWriter(ramDirectory,
                new IndexWriterConfig(new WhitespaceAnalyzer())
                        .setOpenMode(IndexWriterConfig.OpenMode.CREATE));
        Document doc = new Document();
        doc.add(new TextField("f", "test document", Field.Store.NO));
        doc.add(new NumericDocValuesField("boost", 1L));
        indexWriter.addDocument(doc);

        doc = new Document();
        doc.add(new TextField("f", "test document", Field.Store.NO));
        doc.add(new NumericDocValuesField("boost", 2L));


        indexWriter.addDocument(doc);
        IndexReader indexReader = DirectoryReader.open(ramDirectory);
        IndexSearcher indexSearcher = new IndexSearcher(indexReader);

        Query baseQuery = new TermQuery(new Term("f", "test"));
        Query boostQuery = new FunctionQuery(new LongFieldSource("boost"));
        Query q = new CustomScoreQuery(baseQuery, (FunctionQuery) boostQuery);
        indexSearcher.search(q, 10);
    }
}

이번장 끝~!

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다

이 사이트는 스팸을 줄이는 아키스밋을 사용합니다. 댓글이 어떻게 처리되는지 알아보십시오.