본문 바로가기

Dev/.NET

LUCENE.NET 검색엔진


1. LUCENE.NET 


Lucene.Net is a port of the Lucene search engine library, written in C# and targeted at .NET runtime users. The Lucene search library is based on an inverted index. Lucene.Net has three primary goals:


Maintain the existing line-by-line port from Java to C#, fully automating and commoditizing the process such that the project can easily synchronize with the Java Lucene release schedule;

Maintaining the high-performance requirements expected of a first class C# search engine library;

Maximize usability and power when used within the .NET runtime. To that end, it will present a highly idiomatic, carefully tailored API that takes advantage of many of the special features of the .NET runtime.


자바의 유명한 검색 엔진인 Lucene을 이용하여 라인 단위 포팅한 프로젝트 

언어적인 특성으로 인해 C#의 언어의 특성에 맞게 구현 됨 


http://lucenenet.apache.org/


해당 사이트에서 바이너리를 받던가 소스를 받아서 컴파일 하면 됨 



2. Lucene 인덱싱 특징


(1) 디렉토리 단위로 다큐먼트라고 불리는 인덱싱 파일들이 생성 되며, 여러 정의된 스키마를 중복으로 통합 할 수 있음 


(2) 다큐먼드는 파일시스템과 같은 디스크와 메모리에 생성 할 수 있음 

- 메모리에 생성 함으로서 속도를 개선 할 수 있다고는 하나, 경험상 체감할 정도를 아니었음 


(3) 다큐먼트의 필드 특징 

- 기본적으로 텍스트 기반으로 필드를 저장함 


- Field.Index.NO : 필드에 대해서 단순 저장용 데이터로 사용

- Field.Index.ANALYZED : 분석기에 의해 토큰화 된 데이터 

- Field.Index.NOT_ANALYZED : 검색에는 사용되나 분석기를 사용 하지 않고 사용될 데이터


- Field.Store.NO : 원본 데이터를 저장 안함 (Field.Index.ANALYZED 필드에 대해서 공간 절약 할 용도)

- Field.Store.YES : 원본 데이터를 저장 함 


(4) 기본으로 제공 되는 Analyzer(토큰화 하여 분리 시켜 주는 분석기)는 4개가 제공됨 

- WhitespaceAnalyzer : (화이트)스페이스  단위로 토큰 분리 

- SimpleAnalyzer : Letter를 구분으로 토큰 분리 

- StopAnalyzer : SimpleAnalyzer 와 같지만 Stop 단어를 제거함 

- StandardAnalyzer : 문법 기반으로 토큰 분리, 영어권 언어에 적합 



3. Lucene 한글 이슈


(1) 형태소 분석기 및 사전화 인덱싱 

- 한글을 제대로 검색 하기 위해서는 형태소 분석기 및 사전화가 되어 있어야 하나, 이 또한 적합하지 않은 경우가 있음

- 형태소 분석기 및 사전화 작업에 따른 인덱싱 속도 저하와 복잡도 및 관리 리소스가 많이 투입 될 경우가 많음

- 물론 유지보수 및 관리 잘 된다면 검색 품질을 높일 수는 있으나, 요구 사항에 따른 검색 튜닝을 해야함

 

(2) Lucene.Net.Analysis.CJK.CJKAnalyzer 사용 

- 일반적인 쇼핑몰 등의 상품명 및 정보를 검색할 경우 CJK 분석기를 이용하는 것이 유연하게 대처 가능 하다고 봄

- 인덱싱 파일이 커지고 의미상 의미 없는 단어가 검색 되긴 하지만, 기계적으로 인덱싱 속도가 빠름

- 외래어나 기타 사전화 되지 않는 단어에 대해서도 검색이 용이함 

- 3.0,3 버전 이후 부터 contrib 형태로 제공 됨 



4. 인덱싱 및 검색 전략 (Lucene.Net.Analysis.CJK.CJKAnalyzer 사용한다는 전제)


(1) 병합 전략을 위해 유니크한 id 필드를 공통으로 정의 함 (병합시 삭제 + 추가를 위해)


(2) 분석기에 의해 토큰(Field.Index.ANALYZED)화 되어지는 필드를 정하고, 이를 기반으로 보조적인 검색 필드로 일반검색

(Field.Index.NOT_ANALYZED)필드 및 그외 조회되는 데이터(Field.Index.NO)를 정의함 


(3) Field.Index.NOT_ANALYZED의 경우 분석 되지 않는 데이터이므로 대소문자 대응을 해야 함 

- http://www.gossamer-threads.com/lists/lucene/java-dev/74936


(4) 검색의 정렬의 특성상 아래의 정렬 순서로 성능이 좋음 

- http://blog.richeton.com/2009/05/12/lucene-sort-tips/ 


-  SortField.SCORE(적중율), SortField.DOC(인덱싱 문서 순서)으로 정렬, 검색 되어지게 하는 것이 성능상 좋음 

- 사용자 정의 정렬은 되도록이면 SortField.INT 를 사용하여 정렬을 할 수 있도록 인덱싱 처리  

- SortField.STRING의 경우 데이터가 많이 검색 될 경우 위의 검색 옵션 보다 월등히 성능이 좋지 않음 


(5) Lucene 검색 문법

- http://lucene.apache.org/core/3_6_1/queryparsersyntax.html


- SQL 문과 같은 문법으로 사용하기 위해 SQL 파서는 무겁다고 판단

- 아래의 정규식을 이용하여 SQL을 분리해서 Lucene 검색 문법으로 변경 처리 할 수 있음 

* 정규식 : "(?:'(?:[^']|'')*'|-?\d+(?:\.\d+)?(?:[eE]-?\d+)?|\w+|[<>=]{2}|\S)"

select(sel) [ * | field, ... ] 

from    directory 

where   field1='val' and field2='val' or ... 

order by [_score | _doc | field1 [order_expression], ...] 

group by field1, ...   


( *order_expression : [ asc | desc | doc_asc | doc_desc | score_asc | score_desc | int_asc | int_desc ] ) 

( *group result fields : group (group by value), count (group by count) )


(6) 검색 팁 

- Analyzer의 종류에 따라 토큰으로 분리가 되는 데이터가 다르므로 와일드카드 검색등을 이용할 때 고려해야 함 

  (와일드카드 검색은 성능에 영향을 미침)

- CJKAnalyzer는 중국어, 일본어, 한국어에 대해서 두 음절씩 잘라 내므로 와일드카드 검색이 의미 없을 것으로 판단


- 분야별 개수를 가져오는 Faceted Search 같은 기법은 아직 쓸모 있어 보이지 않음 (내가 잘 모를수도..)

- 그냥 직접 해쉬 맵 객체를 이용하여 구현 함 


- 토큰 필드 색인시 기본 문자열 + 공백을 제거한 문자열을 같이 포함 시켜서 넣도록 함 

- 한 글자에 대해서 검색이 용이하게 하려면 단어별로 앞글자를 공백을 넣고 같이 인덱싱 데이터에 넣으면 효과가 있을 것임

- ex) "오페라의 유령 - 25주년 기념 내한공연" 

       -> "오 유 기 내 오페라의유령25주년기념내한공연 오페라의 유령 - 25주년 기념 내한공연"  


- 사용자 검색어에 대해서 공백 단위로 AND 조건 검색 하도록 쿼리 변경 


기타 일반적인 전략 : http://wiki.apache.org/jakarta-lucene/ImproveSearchingSpeed



'Dev > .NET' 카테고리의 다른 글

LUCENE.NET 검색엔진  (0) 2013.01.02
SerializeToXML - C#  (0) 2009.08.10
C# Web Service -> REST  (0) 2009.08.09
Integrating WCF Services with COM+  (0) 2008.09.03
Interop 응용 프로그램 배포  (0) 2007.10.05
RCW, CCW  (0) 2007.10.04