본문 바로가기

Lucene

[lucene] NumberTools를 이용한 부등호 조건절 구현 (>)

루씬에는 RangeQuery가 있습니다.

날짜검색을 할 때나 가격 구간으로 검색 할때 주로 사용됩니다.

PRICE:[20000 TO 30000] 하면
PRICE 필드가 20000에서 30000 사이인 것들이 검색이 됩니다.

그렇다면 PRICE > 30000 이런 상품들을 검색하고 싶다면 어떻게 될까요...?

짧고 무십한 생각으로 PRICE:[30000 TO 9999999] 이렇게도 생각해 봤지만

개념있는 개발자가 할 짓이 아닙니다 -_-

그래서 lucene mailing list에 질문을 보냈고,

루씬인액션 책의 역자 이시자, 예전에 같이 일하셨던 강철구 대리님께 답변을 받았습니다.


How about using NumberTools and range query/filters?

http://lucene.apache.org/java/2_3_2/api/core/org/apache/lucene/document/NumberTools.html

그래서 검색을 하고 연구를 해본결과... 작동합니다 ^^ filter까진 안 쓰더라도
NumberTools만 써도 가능하더군요..

데이터수가 엄청나게 많을때는 filter로 그냥 잘라버리는 것도 좋을 것 같긴 합니다..

아무튼... 위 클래스를 사용하기 위해선 전제조건이 있습니다. 바로, 조건절 필드가 되는 녀석이

색인시에

NumberTools.longToString(lower)를 통해서 색인이 되어야 한다는 것입니다.

즉,
Field field = new Field(id, NumberTools.longToString(Long.parseLong(field_value)), Field.Store.YES,
Field.Index.UN_TOKENIZED);

가 되어야 가능합니다. 위 처럼 색인이 되었다고 가정하고...

간단하게 사용법을 알아보면 굉장히 간단합니다.


Hits hits = r.search(new ConstantScoreRangeQuery("PRICE", NumberTools.longToString(30000L), null, false, true));

면, 30000보다 큰 녀석들만 나옵니다.

참고로 ConstantScoreRangeQuery(String fieldName, String lowerVal, String upperVal, boolean includeLower, boolean includeUpper)

입니다. 하한선,상한선,포함여부까지 설정 할 수 있게 되어있습니다.

혹은 비교 할 값이 String이라면 그냥 "30000" 이렇게 하셔도 됩니다.

즉, Hits hits = r.search(new ConstantScoreRangeQuery("PRICE", "30000", null, false, true));

이런식으로, String으로 값을 줘도 정상적으로 비교를 합니다.

즉, 처음 작성했던 NumberTools.longToString(30000L) 이 것은 value가 Long형일때 사용하면 되겠지요 ^^

참고하세요~

참.. 저 쿼리를 찍어보면 내부적으로는 아래와 같습니다.

PRICE:[30000 TO *]..ㄷㄷㄷㄷ;;;;

앞에서 얘기한 개발자가 할 짓이 아닌 것을 자동으로 해주고 있지요..