GET file/_search?explain=true
{
"query": {
"match": {
"file.name": "test"
}
},
"_source": "file.name",
"sort": [
"_score"
]
}
검색시 explain=true값을 인자로 넘기면, score가 어떻게 계산되었는지 자세히 설명해준다.
아래 _explanation부분을 보자.
{
"value" : 1.6962869,
"description" : "weight(file.objtNm:test in 347841) [PerFieldSimilarity], result of:",
"details" : [
{
"value" : 1.6962869,
"description" : "score(doc=347841,freq=30.0 = termFreq=30.0\n), product of:",
"details" : [
{
"value" : 0.94338167,
"description" : "idf, computed as log(1 + (docCount - docFreq + 0.5) / (docFreq + 0.5)) from:",
"details" : [
{
"value" : 18014.0,
"description" : "docFreq",
"details" : [ ]
},
{
"value" : 46272.0,
"description" : "docCount",
"details" : [ ]
}
]
},
{
"value" : 1.7980919,
"description" : "tfNorm, computed as (freq * (k1 + 1)) / (freq + k1 * (1 - b + b * fieldLength / avgFieldLength)) from:",
"details" : [
{
"value" : 30.0,
"description" : "termFreq=30.0",
"details" : [ ]
},
{
"value" : 1.2,
"description" : "parameter k1",
"details" : [ ]
},
{
"value" : 0.75,
"description" : "parameter b",
"details" : [ ]
},
{
"value" : 102.28585,
"description" : "avgFieldLength",
"details" : [ ]
},
{
"value" : 728.0,
"description" : "fieldLength",
"details" : [ ]
}
]
}
]
}
]
}
score값인 1.6962869는 details array에 있는 두개의 value의 곱이다.
details.value(score) = details.details[0].value * details.details[1].value
details.details[0].value 는 IDF이다.
IDF = log(1 + (docCount - docFreq + 0.5) / (docFreq + 0.5))
IDF( (Inverse Document Frequency)는 위의 수식으로 결정되는데,
결국 docFreq가 낮을수록 IDF가 크다는걸 알 수 있다.
즉, 문서에 해당 키워드가 등장하는 빈도가 작을수록, IDF가 커지면서 score도 올라간다.
details.details[1].value 는 tfNorm이다.
tfNorm = (freq * (k1 + 1)) / (freq + k1 * (1 - b + b * fieldLength / avgFieldLength))
tfNorm(Term Frequency)는 위의 수식으로 결정되는데,
여기서 k1과 b는 가중치를 매기는 정해진 상수이니 무시하고,
freq(문서에 매칭된 키워드 수)이 높을수록
fieldLength(평균 필드의 길이)대비 avgFieldLength(검색된 문서의 필드 길이)가 클수록
TF의 크기가 커지는것을 알수있다.
즉, 검색된 문서에 매칭된 키워드수가 자주 반복될수록, 또 평균 필드 길이보다 검색된 문서의 필드가 길수록 score가 올라간다.
종합해보자면 BM25 알고리즘에서 score는 아래와 같이 계산되고
score = TF * tfNorm
전체 문서에서 해당 키워드가 등장하는 빈도가 작을수록, 즉 해당 문서에만 검색되는 독특한 단어일수록, 검색된 문서에 해당 키워드가 자주 반복될수록 score는 올라간다.
기존 TF-IDF보다 BM25가 더 정교한 score계산을 하기 때문에 lucene도 BM25를 적용하였고 따라서 elasticsearch도 6.3버전부터 score계산에 BM25알고리즘을 적용하고 있다고 한다.