## 목차 ##
- 1. 필드 캐시
- 2. 검색 결과 정렬
- 3. 여러 개의 필드를 동시에 검색
- 4. 스팬 질의
- 5. 검색 필터
- 6. 다수의 루씬 색인 검색
- 7. 텀 벡터 활용
- 8. FieldSelector로 필드 선택
- 9. 검색 중단
## 1. 필드 캐시 ##
문서의 특정 필드 값을 빠르게 조회해야 할 경우에 사용
- 특정 필드의 값을 순차적으로 조회할 목적으로 만든 루씬 내부 API
필드 캐시를 사용하기 위해서는 해당 필드에 하나의 텀만 들어있어야한다.
Index.NOT_ANALYZED
혹은Index.NOT_ANALYZED_NO_NORMS
(1) 모든 문서의 필드 값 불러오기
- 필드 캐시를 사용하면 색인 모든 문서의 특정 필드 값 배열을 받아올 수 있다.
float[] weights = FieldCache.DEFAULT.getFloats(reader, "weight");
float value = wegihts[docID];
필드캐시 초기화는 색인 크기에 따라 시간이 오래 걸릴 수 있다.
필드 캐시는 많은 메모리를 잡아먹을 수도 있다.
- 특히 String
(2) 세그먼트별 IndexReader
- 루씬 2.9부터 검색, 정렬은 세그먼트 단위로 동작한다.
## 2. 검색 결과 정렬 ##
검색 결과는 기본적으로 연관도 점수의 내림차순 정렬
루씬에서는 사용자 정의 정렬 기법 제공
- 필드 캐시를 사용한다.
- ex) 특정 필드값을 기준으로 정렬
(1) 필드 값으로 정렬
IndexSearcher.search(Query, Filter, int, Sort)
메소드 사용
...
TopDocs resultDocs = searcher.search(query, null, 10, sort);
for(ScoreDoc scoreDoc : resultDocs.scoreDocs) {
int docID = scoreDoc.doc;
Document doc = searcher.doc(docID);
System.out.println(doc);
}
...
(2) 연관도 순서로 정렬
- 루씬의 기본 정렬 설정
search(query, null, 10, null)
혹은search(query, 10)
- 연관도 점수가 같으면 docID 순서로 정렬
(3) 색인 순서로 정렬
문서 ID 순서로 정렬
search(query, null, 10, Sort.INDEXORDER)
(4) 필드 값으로 정렬
정렬하고자 하는 필드에 하나의 텀만 있어야한다.
필드값 기준 정렬은 기본적으로 오름차순
SortField
객체 사용
...
Sort sort = new Sort(new SortField("category", SortField.STRING));
//Sort sort = new Sort(new SortField("category", SortField.STRING, true)); //역방향 인자로 true를 지정하면 내림차순 정렬
searcher.search(query, null, 10, sort);
...
(5) 여러 필드 값으로 정렬
Sort
객체 생성 시 여러개의SortField
를 넘겨줄 수 있다.
Sort sort = new Sort(new SortField("category", SortField.STRING),
SortField.FIELD_SCORE,
new SortField("pubmonth", SortField, true));
## 3. 여러 개의 필드를 동시에 검색 ##
MultiFieldQueryParser
클래스 사용
...
//title 혹은 subject 필드에 "lucene"을 포함하는 쿼리 생성
QueryParser parser = new MultiFieldQueryParser(Version.LUCENE_30,
new String[]{"title", "subject"},
new SimpleAnalyzer());
//title과 subject필드 모두에 "lucene"을 포함하는 쿼리 생성
QueryParser parser2 = new MultiFieldQueryParser(Version.LUCENE_30,
new String[]{"title", "subject"},
new BooleanClause.Occur[]{Occur.MUST, Occur.MUST},
new SimpleAnalyzer());
Query query = parser.parse("lucene");
...
## 4. 스팬 질의 ##
스팬(span)이란?
- 문서 필드에서 토큰이 있는 위치 정보
루씬은
SpanQuery
를 기반으로 하는 여러가지 하위 클래스들을 내장하고 있다.SpanTermQuery
SpanFirstQuery
SpanNearQuery
SpanNotQuery
FieldMaskingSpanQuery
SpanOrQuery
검색어 토큰의 위치 정보를 같이 검색
PhraseQuery
에 비해 위치정보를 좀 더 명확하게 표현PhraseQuery
는 slop값 지정까지만 가능
문서를 찾아내는거에 더해 텀의 위치정보 계산이 추가되어 처리량이 많다.
- ex)
SpanTermQuery
는 텀을 포함하는 문서를 찾아낸 뒤 텀의 위치정보까지 계산한다.
- ex)
(1) SpanTermQuery
모든
SpanQuery
하위 클래스를 사요하기 위한 시작 질의모든
SpanQuery
하위 클래스는SpanTermQuery
객체를 넘겨받아 동작한다.
...
doc.add(new Field("field",
"the quick brown fox jumps over the lazy dog",
Field.Store.YES,
Field.Index.ANALYZED));
doc.add(new Field("field",
"the quick red fox jumps over the sleep cat",
Field.Store.YES,
Field.Index.ANALYZED));
...
Term term1 = new Term("field", "brown");
Term term2 = new Term("field", "red");
SpanTermQuery brown = new SpanTermQuery(term1);
SpanTermQuery red = new SpanTermQuery(term2);
위에서 만들어놓은 색인 문서와 질의 객체를 사용해 SpanQuery의 종류를 하나씩 보자.
(2) SpanFirstQuery
- 필드의 맨 앞에서 일정 범위 안에 있는 문서 검색
//brown 스팬텀쿼리 객체를 넘겨주고 필드의 앞에서 2번째 위치내에 있는 문서 검색
SpanFirstQuery sfq = new SpanFirstQuery(brown, 2);
searcher.search(sfq, 10);
sfq = new SpanFirstQuery(brown, 3);
searcher.search(sfq, 10);
"the quick brown fox jumps over the lazy dog" 구문에서 brown은 3번째 위치에 존재하므로 첫 번째 검색 결과문서는 0개이고 두 번째 검색 문서 결과는 1이다.
(3) SpanNearQuery
PhraseQuery
와 마찬가지로 가까이 있는 텀을 찾아준다.- 일정 거리 안에 있는 스팬을 찾아준다.
- 순서대로 위치해야 하는지 아닌지를 설정 가능하다.(
inOrder
값)
SpanQuery[] quick_brown_dog = new SpanQuery[]{quick, brown, dog};
//quick,brown,dog가 스팬 없이(0), 순서대로(true) 오는 문서 검색
SpanNearQuery snq = new SpanNearQuery(quick_brown_dog, 0, true);
searcher.search(snq, 10);
//검색 결과 0건
//quick,brown,dog가 사이 스팬이 5 이내이고 순서대로 오는 문서 검색
snq = new SpanNearQuery(quick_brown_dog, 5, true);
searcher.search(snq, 10);
//검색결과 1건
이외에도 SpanNotQuery
와 SpanOrQuery
가 있는데 쓸 일이 있을까 싶다. 있으면 찾아보자.
## 5. 검색 필터 ##
필터를 적용하면 검색 대상을 줄여준다.
- 색인의 일부 문서만 대상으로 검색 실행
- 이전에 검색한 결과 안에서만 검색하는 결과 내 검색 기능 구현
IndexSearch(Query, Filter, int, Sort)
메소드에 필터 전달하여 검색
(1) TermRangeFilter
문자열 필드에 적용하는 필터
TermRangeQuery
와 동일하나 연관도 점수는 계산하지 않는다.특정 필드 값의 문자열 범위 지정
//title 필드의 값이 'a'~'c'로 시작하는 문서만 검색하는 필터. a포함(true), c포함(true)
Filter filter = new TermRangeFilter("title", "a", "c", true, true);
//title 필드의 값이 'h'로 시작하는 문서만 검색하는 필터.
Filter filter2 = new TermRangeFilter("title", "h", null, true, false);
마지막 인자 두 개는 includeLower
, includeUpper
이며 범위의 시작 값, 끝 값을 포함할 것인지의 여부를 지정한다.
(2) NumericRangeFilter
숫자 값이 들어있는 필드의 범위로 필터링
NumericRangeQuery
와 동일하나 연관도 점수를 계산하지 않는다.
//pubmonth 필드의 값이 2001년6월~2001년9월 사이인 문서만 검색하는 필터
Filter filter = new NumericRangeFilter("pubmonth", 200106, 200109, true, true);
(3) FieldCacheRangeFilter
TermRangeFilter
,NumericRangeFilter
같은 기능이지만 필드 캐시를 사용한다.
Filter filter1 = FieldCacheRangeFilter.newStringRange("title", "d", "j", true, true);
Filter filter2 = FieldCacheRangeFilter.newFloatRange("score", 1.0f, 5.0f, false, false);
(4) QueryWrapperFilter
- 쿼리를 필터로 변환
Query query = new TermQuery("title", "lucene");
Filter filter = new QueryWrapperFilter(query);
(5) SpanQueryFilter
QueryWrapperFilter
와 같은 역할을 하지만 추가적으로 스팬 관련 정보를 유지한다.QueryWrapperFilter
보다 느리므로 굳이 스팬 정보가 필수가 아니라면 사용하지 않는것이 좋다.
이외에도 루씬 공식 문서를 보면 다양한 내부 필터를 지원한다. 뿐만 아니라 contrib 모듈에서는 여러 종류의 필터가 제공된다.
(6) 필터와 BooleanQuery
- 필터 기능은
BooleanQuery
에서 조건을 추가하는 것으로 모두 대신할 수 있다.- 결과로 받는 문서는 같다.
CachingWrapperFilter
등을 활용하면 필터를 캐시하고 재사용할 수 있다.- 검색 대상 문서가 다르기 때문에 idf 점수가 달라진다.
CachingWrapperFilter
등을 활용하면
## 6. 다수의 루씬 색인 검색 ##
(1) MultiSearcher
- 여러개의 색인 각각
IndexSearcher
를 따로 사용- 각 색인별로 결과를 취합하고 문서를 정렬해서 반환
...
IndexSearcher[] searchers = new IndexSearcher[2];
searchers[0] = new IndexSearcher(directory0);
searchers[1] = new IndexSearcher(directory1);
//IndexSearcher[] 배열을 MultiSearcher의 생성자에 넘긴다.
MultiSearcher searcher = new MultiSearcher(searchers);
TopDocs hits = searcher.search(query, 10);
...
(2) ParallelMultiSearcher
MultiSearcher
와 같은 기능이지만 개별IndexSearcher
마다 스레드를 활용해 검색한다.- 멀티코어이면서 개별 인덱스가 다른 디스크에 저장된 환경에서 유용
## 7. 텀 벡터 활용 ##
## 8. FieldSelector로 필드 선택 ##
## 9. 검색 중단 ##
'프레임워크 > 루씬(Lucene)' 카테고리의 다른 글
(루씬) 3 - 검색(Search) (0) | 2020.05.16 |
---|---|
(루씬) 2 - 색인(Indexing) (0) | 2020.05.16 |
(루씬) 1 - 루씬과의 만남 (0) | 2020.05.16 |