http://softwaregeeks.org/blog/271
트랙백을 남겨주신 짐승님의 글을 보고 ... ^^
항상 검색 엔진의 인덱스 파일의 용량이 대용량으로 가면서 문제 되는 것이
정렬 문제 였다.
그러던 중 짐승님이 남겨주신 트랙백의 글을 보고 정신이 탁 트여지는 것을 느꼈다.
예전에도 루씬의 DocScore를 가중치나 계산 공식 변경등을 통해 수정 할 수 있다는 것은 알았었는데
그 score자체가 정렬과 연관이 지어지지를 않고 있었다.
그런데 짐승님의 (아 이거 어감이 정말..-_-;;;) 글 http://softwaregeeks.org/blog/271 을 보고나니
뭔가 탁~~~ 하고 깨이는 느낌..
나는 왜 저렇게 생각의 전환이 안 되는거지... -.-;
안그래도 회사에서 로그 분석을 간단하게 루씬으로 구현하면서
이 정렬 문제가 대두되고 있었는데, 바로 한번 적용을 해보았다.
바로 CustomScoreQuery
아래 예제 클래스에서 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 하고는 큰.. 관계는 없겠네요..
트랙백을 남겨주신 짐승님의 글을 보고 ... ^^
항상 검색 엔진의 인덱스 파일의 용량이 대용량으로 가면서 문제 되는 것이
정렬 문제 였다.
그러던 중 짐승님이 남겨주신 트랙백의 글을 보고 정신이 탁 트여지는 것을 느꼈다.
예전에도 루씬의 DocScore를 가중치나 계산 공식 변경등을 통해 수정 할 수 있다는 것은 알았었는데
그 score자체가 정렬과 연관이 지어지지를 않고 있었다.
그런데 짐승님의 (아 이거 어감이 정말..-_-;;;) 글 http://softwaregeeks.org/blog/271 을 보고나니
뭔가 탁~~~ 하고 깨이는 느낌..
나는 왜 저렇게 생각의 전환이 안 되는거지... -.-;
안그래도 회사에서 로그 분석을 간단하게 루씬으로 구현하면서
이 정렬 문제가 대두되고 있었는데, 바로 한번 적용을 해보았다.
바로 CustomScoreQuery
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
FieldScoreQuery qValSrc = new FieldScoreQuery("count",FieldScoreQuery.Type.INT); //여기에 지정된 필드가 점수의 직접적인 요소가 된다. | |
Query resultQuery = QueryBuilder.build(parameter); //자체적으로 만든 쿼리 빌더. 그냥 Query를 리턴함 | |
resultQuery = new CustomAddScoreQuery(resultQuery, qValSrc); //만들어진 쿼리와 FieldScoreQuery를 사용하여 CustomScoreQuery를 상속한 쿼리를 생성 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | |
} | |
} |
아래 예제 클래스에서 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를 사용하는 것 보다 훨씬 빠른 결과를 가져 올 수 있다.
짐승님이 걸어주신 트랙백 덕분에
너무 좋은 것을 알게 되었습니다. 감사합니다. ^^