본문 바로가기

Lucene

Lucene 3.0 그리고 CustomScoreQuery.

http://softwaregeeks.org/blog/271

트랙백을 남겨주신 짐승님의 글을 보고 ... ^^

항상 검색 엔진의 인덱스 파일의 용량이 대용량으로 가면서 문제 되는 것이
정렬 문제 였다.

그러던 중 짐승님이 남겨주신 트랙백의 글을 보고 정신이 탁 트여지는 것을 느꼈다.

예전에도 루씬의 DocScore를 가중치나 계산 공식 변경등을 통해 수정 할 수 있다는 것은 알았었는데
그 score자체가 정렬과 연관이 지어지지를 않고 있었다.

그런데 짐승님의 (아 이거 어감이 정말..-_-;;;) 글 http://softwaregeeks.org/blog/271 을 보고나니
뭔가 탁~~~ 하고 깨이는 느낌..

나는 왜 저렇게 생각의 전환이 안 되는거지... -.-;

안그래도 회사에서 로그 분석을 간단하게 루씬으로 구현하면서
이 정렬 문제가 대두되고 있었는데, 바로 한번 적용을 해보았다.

바로 CustomScoreQuery


FieldScoreQuery qValSrc = new FieldScoreQuery("count",FieldScoreQuery.Type.INT); //여기에 지정된 필드가 점수의 직접적인 요소가 된다.
Query resultQuery = QueryBuilder.build(parameter); //자체적으로 만든 쿼리 빌더. 그냥 Query를 리턴함
resultQuery = new CustomAddScoreQuery(resultQuery, qValSrc); //만들어진 쿼리와 FieldScoreQuery를 사용하여 CustomScoreQuery를 상속한 쿼리를 생성
view raw 1.java hosted with ❤ by GitHub


public class CustomAddScoreQuery extends CustomScoreQuery {
// constructor
public CustomAddScoreQuery (Query q, ValueSourceQuery qValSrc) {
super(q,qValSrc);
}
@Override
public String name() {
return "CustomAddScoreQuery";
}
@Override
public float customScore(int doc, float subQueryScore, float valSrcScore) {
return subQueryScore + valSrcScore;
}
//루씬 소스의 테스트 클래스 참고
@Override
public Explanation customExplain(int doc, Explanation subQueryExpl, Explanation valSrcExpl) {
float valSrcScore = valSrcExpl==null ? 0 : valSrcExpl.getValue();
Explanation exp = new Explanation( valSrcScore + subQueryExpl.getValue(), "custom score: sum of:");
exp.addDetail(subQueryExpl);
if (valSrcExpl != null) {
exp.addDetail(valSrcExpl);
}
return exp;
}
}
view raw 2.java hosted with ❤ by GitHub


아래 예제 클래스에서 customScore의 float valSrcScore는 ValueSourceQuery의 점수고 이 ValueSourceQuery는
FieldScoreQuery가 extends하여 구현하고 있다. 대략 보면.. count 필드의 값이 내부적으로 정규화 과정을 거쳐서
점수로 환산되고 이것이 subQueryScore (루씬의 일반적인 랭킹 점수) 와 합산 되는 듯 하다.

FieldScoreQuery.Type은 4가지가 존재하는데 각각의 타입에 따라서 필요한 RAM의 양이 다르다고 나와있다.

INT는 4 * maxDocs bytes
FLOAT은 8 * maxDocs bytes
SHORT는 2 * maxDocs bytes
BYTE는 1 * maxDocs bytes..

아마 각 타입에 따른 정규화 과정 때문에 그런 것 같기도 하고..

아무튼 자세히 파보지는 않아서 정확히는 모르겠지만...
위 count 필드가 검색회수라고 가정하면 위의 쿼리로는 가장 검색 회수가 많은 순 부터
검색이 된다.

기본적으로 검색을 다 해 놓은 결과 SET을 가지고 다시 정렬을 하는 것이 아니기 때문에
Sort를 사용하는 것 보다 훨씬 빠른 결과를 가져 올 수 있다.

짐승님이 걸어주신 트랙백 덕분에
너무 좋은 것을 알게 되었습니다. 감사합니다. ^^

이 글 자체는 Lucene 3.0 하고는 큰.. 관계는 없겠네요..