본문 바로가기

Lucene

[Lucene] coord와 Match Term 가져오기

방명록에 남겨진 질문 중 하나에 대한
답을 찾아보려고 이것저것 해보다가 우선 생각나는 방법이 있어서
적어보려고 합니다.

질문의 내용은
루씬의 Explain에서..

0.5987479 = (MATCH) product of:

1.4968698 = (MATCH) sum of:

0.7484349 = (MATCH) weight(label:시크릿 in 0), product of:

0.40649435 = queryWeight(label:시크릿), product of:

2.9459102 = idf(docFreq=1, maxDocs=14)

0.13798599 = queryNorm

1.8411939 = (MATCH) fieldWeight(label:시크릿 in 0), product of:

1.0 = tf(termFreq(label:시크릿)=1)

2.9459102 = idf(docFreq=1, maxDocs=14)

0.625 = fieldNorm(field=label, doc=0)

0.7484349 = (MATCH) weight(label:가든 in 0), product of:

0.40649435 = queryWeight(label:가든), product of:

2.9459102 = idf(docFreq=1, maxDocs=14)

0.13798599 = queryNorm

1.8411939 = (MATCH) fieldWeight(label:가든 in 0), product of:

1.0 = tf(termFreq(label:가든)=1)

2.9459102 = idf(docFreq=1, maxDocs=14)

0.625 = fieldNorm(field=label, doc=0)

0.4 = coord(2/5) 


Match된 Term 정보와 Coord의 정보를 보고 싶다는 것이었는데요
내부 소스를 따라가기가 쉽지 않더라구요..
Explain 정보를 생성해가는 과정에서 지속적으로 정보를 붙여나가도록 되어있기도 하고요..

생각해보니 점수가 아니라 Term 정보와 Coord 값이라면
단순하게 가져 올 수도 있지 않을까 해서 작성해보았습니다.

Explain 메서드를 따라가보면 거의 검색을 한번 더 수행하는 수준의 로직으로 구현이 되어있습니다.

리소스 문제도 있겠지만
따라가기가 정말 어렵더군요 --; 각각의 Explain 항목을 Object로 가져오는 형식이 아니라
검색 수행단계별로 결과 값을 append하여 만드는 형식이라서 중간의 어느 한가지 항목만
가져오는 것이 쉽지 않아 보였습니다.

일단, 질문자께서 원하신 것이 "Match된 키워드와 Coord의 값"이었기 때문에
Analyzer의 TokenStream과 TermVector를 사용하면 꼼수를 부릴 수 있지 않을까 싶어서 만들어보았습니다.

Query에 사용된 질의문을 Analyzer를 사용해 각 Term으로 분리하고 (물론 색인에 사용된 Analyzer여야겠죠)
검색되어 나온 Document의 TermVector를 얻어서 비교하는 방식입니다.

Document는 아래와 같이 2개가 색인 되었다고 가정하겠습니다.

0 : 시크릿 가든 여자배우
1 : 자바 구글 앱 엔진


그리고 이 두개의 문서는 WhitespaceAnalyzer를 사용하여 색인 하였습니다.
또한 색인시 Field 명은 "label"로 옵션으로는 TermVector.YES를 추가하였습니다.




소스는 아래와 같습니다.


IndexReader로부터 검색 된 Document의 ID로 TermFreqVector를 가져옵니다. 이 Object는 해당 Document가
가지고 있는 Term과 각 Term의 개수가 들어있습니다. 물론 색인시 사용된 Analyzer (여기에서는 WhitespaceAnalyzer)에 의해서 추출 된 Term 일 것 입니다.

또한, 질의문을 Analyzer로 다시 분석하여 Term을 얻어냅니다. 그리고 그 Term의 개수가 coord에서의 분모가 되는
maxOverlap의 값이 될 수 있습니다.

이렇게 질의문에서 얻은 Term과 Document에서 얻은 TermFreqVector의 Term을 비교하면
실제 Match된 Term의 개수를 알 수 있는데요 이것이 coord에서 overlap의 값이 됩니다.

위 예제의 경우 결과는 아래와 같습니다.

 [시크릿]

maxOverLap : 1
overLap : 1



만약 질의문을 "시크릿 자바"로 한다면 검색 Document는 2개가 될 것이고
결과는 아래와 같이 나옵니다.

 [시크릿]
maxOverLap : 2
overLap : 1
 
[자바]
maxOverLap : 2
overLap : 1

질의문이 "시크릿 오케이 굿 잡" 이라면
아래와 같이 나올 것 입니다.

[시크릿]
maxOverLap : 4
overLap : 1


제가 현재 알고 있는 지식으로는 이정도가 될 것 같은데..아마 분명히 Explain의 각 값을
쉽게 가져 올 수 있는 그리고 실제 구현된 값대로 가져 올 수 있는 방법이 있을 것 같은데 잘 모르겠네요..ㅋ

질문자분께 도움이 되었으면 좋겠습니다.