루씬에는 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 *]..ㄷㄷㄷㄷ;;;;
앞에서 얘기한 개발자가 할 짓이 아닌 것을 자동으로 해주고 있지요..
날짜검색을 할 때나 가격 구간으로 검색 할때 주로 사용됩니다.
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/
그래서 검색을 하고 연구를 해본결과... 작동합니다 ^^ 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 *]..ㄷㄷㄷㄷ;;;;
앞에서 얘기한 개발자가 할 짓이 아닌 것을 자동으로 해주고 있지요..