본문 바로가기

Lucene

[about Lucene] 루씬으로 검색엔진 개발하기 Sort와 CustomScore 검색결과에 대한 기본적인 정렬은 TF-IDF에 의한 유사도 점수입니다. 하지만 검색결과를 우리의 입맛대로 조절해야 하는 경우가 있습니다. 이를 위해서 루씬에서는 Sort클래스와 그외 몇가지 확장 가능한 API를 제공합니다. 여기서는 우선 Sort클래스의 기본적인 사용법을 확인해보겠습니다. SortTest.java 보시면 2개 필드에 대해서 정렬을 하고 있습니다. Sort클래스의 사용은 우선 정렬에 사용 할 SortField를 생성하고 이를 사용해 Sort클래스의 인스턴스를 만들어서 IndexSearcher를 통해 검색을 합니다. 여태까지 IndexSearcher로부터 받아오는 결과 클래스가 TopDocs였지만 필드 정렬을 사용 할 때는 TopFieldDocs라는 클래스로 결과가 받아집니다. 이 외에도 C.. 더보기
[about Lucene] 루씬으로 검색엔진 개발하기 Query와 Filter 이번 포스트에서는 루씬에서 사용되는 Query와 Filter의 기본적은 사용예제를 보여드리려고 합니다. 다시 예전에 작성했던 IndexSearcherTest의 메서드들을 살펴보면 4가지 쿼리 타입에 대해서 테스트 케이스가 작성되어 있는 것을 보실 수 있습니다. IndexSearcherTest.java 각 메서드를 간단하게 살펴보면 우선 searchByTerm 메서드에서는 Term을 사용하여 Query를 만들고 있습니다. Term t = new Term("ids", "1"); Query q = new TermQuery(t); 위 쿼리는 ids 필드에서 값이 1인 Document를 검색하고 싶다는 뜻입니다. searchByBooleanQuery 메서드에서는 Term을 사용한 Query 2개를 BooleanQ.. 더보기
[about Lucene] 루씬으로 검색엔진 개발하기 - Near Realtime Search- 이번 글에서는 루씬인액션에서 소개되고 있는 Near Realtime Search에 대해서 작성해보려고 합니다. 기본적으로 IndexSearcher는 IndexWriter에 의한 변경 사항을 바로바로 반영하지를 못 합니다. 일반적으로 commit이 된 이후 IndexSearcher를 새로 생성하여야 IndexWriter에 의한 변경된 내용을 반영 할 수 있습니다. 제가 내부적으로 구현하여 사용하고 있는 프로그램에서도 이러한 부분을 Searcher를 새로 만들어서 사용하고 있습니다. RealTimeSearch.java 파일명은 RealTimeSearch이지만 사실 RealTimeSearch에 대한 예제는 아닙니다. 지금까지 루씬에서 IndexWriter에 의한 변경을 IndexSearcher에서 반영하기 위.. 더보기
[about Lucene] 루씬으로 검색엔진 개발하기 - IndexSearcher- 앞선 포스트에서 IndexWriter를 사용한 색인을 알아보았습니다. 이번에는 IndexSearcher를 사용한 Document 검색과 검색을 할 때 사용되는 Query에 대해서 알아보고 더불어..Filter까지도 함께 알아보도록 하겠습니다. 우선 간단한 IndexSearcher의 테스트 케이스입니다. IndexSearcherTest.java 특별히 어려운 코드는 없을 것 입니다. 테스트 케이스가 4가지가 있는데요 나중에 이야기 할 Query 종류에 따른 사용을 보여드리기 위해서 각각 테스트 케이스를 작성하였습니다. IndexSearcher를 사용 할 때의 주의 할 점은 여러가지가 있겠지만 그 중 가장 중요한 것이 IndexSearcher의 생성은 비용이 많이 들어가는 부분이기 때문에 가급적 단일 인스턴.. 더보기
[about Lucene] 루씬으로 검색엔진 개발하기 - IndexWriter - 루씬으로 뭔가 작업을 한다면 사실 가장 어려운 부분이 Analyzer를 입맛에 맞게 만드는 부분일 것 입니다. 지금까지 작성한 Analyzer에 대한 내용이 이렇게 길었던 것도 그런 이유였고요... 이제부터 이야기 할 Indexing, Search, Query, Sort등은 사실 사용하기가 그렇게 어려운 것은 아닙니다. 이미 API자체가 너무나도 잘 만들어졌기 때문에 그냥 특별한 옵션 없이 사용하는 것 만으로도 충분히 잘 사용 할 수가 있습니다. 그 다음엔 사실 경험이구요... 포스트의 내용도 기본적인 API에 대한 테스트케이스와 이것들을 사용하면서 기억에 남았던 내용들에 대한 것을 소개해드리는 내용이 될 것 같습니다. 사실 대부분의 내용은 JAVADOC이나 루씬인액션과 같은 책을 읽어보는 것이 훨씬 도.. 더보기
[Lucene] similiarity simple java code static double cosine_similarity(Map v1, Map v2) { Set both = Sets.newHashSet(v1.keySet()); both.retainAll(v2.keySet()); double sclar = 0, norm1 = 0, norm2 = 0; for (String k : both) sclar += v1.get(k) * v2.get(k); for (String k : v1.keySet()) norm1 += v1.get(k) * v1.get(k); for (String k : v2.keySet()) norm2 += v2.get(k) * v2.get(k); return sclar / Math.sqrt(norm1 * norm2); } http://stackoverflo.. 더보기
[about Lucene] 루씬으로 검색엔진 개발하기 - Analyzer (6) - 이번에는 많은 분들께서 기다리셨을(?) 명사 추출 필터입니다. 사전에 등록되어있는 명사를 기반으로 Tokenizer나 선행 TokenFilter로 부터 넘어온 Token을 탐색하여 명사를 추출해내는 구조입니다. 기대를 하셨다면 죄송스럽게도 굉장히 별거 없는 Filter입니다. 형태소 분석이 아닌 단순히 Token을 읽어 사전에 있는 단어를 추출하는 방식입니다. Token탐색도 그냥 character단위로 쭉.... 합니다. 이걸 다른 자료구조형으로 만들면 속도를 빠르게 할 수도 있겠지만 여기서는 코드의 간결함을 위해서 복잡한 부분은 모두 제외를 시킬 예정입니다. 이 추출의 과정이 형태소분석을 기반으로 알고리즘이 만들어져 있다면 이 Filter가 형태소분석기가 됩니다. 하지만 이 형태소분석이라는 것이 쉬운.. 더보기
현재 사용중인 루씬쪽.. 약간의 변경 작업 로그분석/조회 프로그램에 대한 루씬쪽 약간의 변경작업.. 1. 전체 document 약 2억6천만개 - 하루 약 40만개씩 증가 - 색인파일 연도별로 분리 - MultiSearcher 사용 2. 검색속도 개선을 위한 작업 - date필드를 int형 필드로 마이그레이션 - value 필드를 int형 필드로 마이그레이션 - rangeQuery를 Filter로 변경하여 검색 3. 리소스 개선을 위한 작업 - long타입을 int로 마이그레이션 까지는 완료... 4. 더 할 수 있는 작업 - 색인 조건 최적화 - TermVector, Norm값등은 필요 없으므로 가지고 가지 않도록 5. replication 기능 개발 역시 책을 읽어야해...;; 1판에 있던 내용도 지금 다시 읽으니 참 새롭다. 더보기
[about Lucene] 루씬으로 검색엔진 개발하기 - Analyzer (5) - 이번에는 동의어 필터를 만들어보겠습니다. 동의어의 역할은 다 아시겠지만 특정한 키워드에 대해서 확장된 검색을 지원 할 수 있도록 해줍니다. 이 예제도 앞선 예제들과 마찬가지로 루씬인액션의 책에 있는 예제를 보고 우리 상황에 맞춰 다시 만든 코드들입니다. 먼저 테스트 케이스를 보겠습니다. DevysSynonymFilterTest.java 테스트 케이스는 양방향으로 검사를 하고 있습니다. 동의어 목록을 미리 지정해두고 TokenFilter로부터 나오는 Token을 리스트와 비교.. 그리고 이 Token을 따로 저장해두고 다시 동의어 목록을 가지고 비교합니다. 예를 들어서 동의어가 "노트북, notebook, 노트북PC"로 등록되어 있다면 3개 중 하나의 키워드가 검색쿼리로 들어온다고 해도 동의어로 등록된 3.. 더보기
[about Lucene] 루씬으로 검색엔진 개발하기 - Analyzer (4) - 앞선 포스트에서는 Analyzer의 기본이 되는 Tokenizer를 구현하여 보았습니다. 다시 한번 말씀드리면 Analyzer는 Reader - Tokenizer - TokenFilter - TokenFilter - TokenFilter... 이런식으로 1개의 Tokenizer와 N개의 TokenFilter로 구성이 되어있습니다. 여기서는 그 TokenFilter 중 하나를 구현해보려 합니다. 앞에서 여러개의 Filter를 말씀드렸었습니다. 기본적으로 "어미사전"으로부터 어미를 제거하는 StemFilter "동의어 사전"으로부터 동의어를 추출하는 SynonymFilter "명사사전"으로부터 명사를 추출하는 NounExtractFilter "불용어사전"으로부터 불용어 처리를 하는 StopFilter "복합.. 더보기