Imagine that we have a website that hosts blog posts and enables users to vote for the blog posts that they like. We would like more-popular posts to appear higher in the results list, but still have the full-text score as the main relevance driver. We can do this easily by storing the number of votes with each blog post:
사용자들이 자기가 좋아하는 블로그 게시물에 투표할 수 있는 기능이 있는 website를 가정해 보자. 결과 목록에서 더 높게 나타나는 더 인기 있는 게시물을 좋아하겠지만, 여전히 full-text score를 relevance score로 가져야 한다. 각 블로그 게시물의 투표 수를 저장하면, 간단하게 이것을 할 수 있다.
PUT /blogposts/post/1 { "title": "About popularity", "content": "In this post we will talk about...", "votes": 6 }
At search time, we can use the function_score
query with the field_value_factor
function to combine the number of votes with the full-text relevance score:
검색 시에, 투표 수와 full-text relevance score를 조합하기 위하여, field_value_factor
function으로 function_score
query를 사용할 수 있다.
GET /blogposts/post/_search { "query": { "function_score": { "query": { "multi_match": { "query": "popularity", "fields": [ "title", "content" ] } }, "field_value_factor": { "field": "votes" } } } }
| |
main query가 먼저 실행된다. | |
| |
모든 document는 |
In the preceding example, the final _score
for each document has been altered as follows:
위의 예에서, 각 document에 대한 최종 _score
는 아래처럼 변경된다.
new_score = old_score * number_of_votes
This will not give us great results. The full-text _score
range usually falls somewhere between 0 and 10. As can be seen in Figure 29, “원래의 _score
가 2.0
인 경우 인기의 선 그래프”, a blog post with 10 votes will completely swamp the effect of the full-text score, and a blog post with 0 votes will reset the score to zero.
위에서 좋은 결과가 나오지는 않을 것이다. full-text _score
의 범위는 일반적으로 0 ~ 10 사이의 어디쯤일 것이다. Figure 29, “원래의 _score
가 2.0
인 경우 인기의 선 그래프”에서 볼 수 있듯이, 투표수가 10인 블로그 게시물은 full-text score의 효과를 완전히 뒤덮을 것이고, 투표수가 0인 게시물은 score가 0이 될 것이다.
modifieredit
A better way to incorporate popularity is to smooth out the votes
value with some modifier
. In other words, we want the first few votes to count a lot, but for each subsequent vote to count less. The difference between 0 votes and 1 vote should be much bigger than the difference between 10 votes and 11 votes.
인기를 통합하는 더 나은 방법은, 어떤 modifier
로 votes
값을 일정부분 제거하는 것이다. 즉, 처음 몇 번은 votes를 많이 세고, 그 뒤의 votes는 덜 세는 것이다. votes 0과 1의 차이는 10과 11의 차이보다 훨씬 더 커야 한다.
A typical modifier
for this use case is log1p
, which changes the formula to the following:
이 예를 위한 대표적인 modifier
는 log1p
이다. 따라서 수식은 아래처럼 변경된다.
new_score = old_score * log(1 + number_of_votes)
The log
function smooths out the effect of the votes
field to provide a curve like the one in Figure 30, “원래의 _score
가 2.0
인 경우 인기의 log 그래프”.
log
function은, Figure 30, “원래의 _score
가 2.0
인 경우 인기의 log 그래프”와 같은 곡선을 나타내기 위해, votes
field의 값을 일정 부분 제거한다.
The request with the modifier
parameter looks like the following:
modifier
매개변수를 이용한 request는 아래와 같다.
GET /blogposts/post/_search { "query": { "function_score": { "query": { "multi_match": { "query": "popularity", "fields": [ "title", "content" ] } }, "field_value_factor": { "field": "votes", "modifier": "log1p" } } } }
The available modifiers are none
(the default), log
, log1p
, log2p
, ln
, ln1p
, ln2p
, square
, sqrt
, and reciprocal
. You can read more about them in the field_value_factor
documentation.
이용할 수 있는 modifier에는 none
(기본), log
, log1p
, log2p
, ln
, ln1p
, ln2p
, square
, sqrt
그리고 reciprocal
이 있다. 더 많은 정보를 위해 field_value_factor
documentation를 참고하자.
factoredit
The strength of the popularity effect can be increased or decreased by multiplying the value in the votes
field by some number, called the factor
:
votes
field에 있는 값에 어떤 숫자를 곱하여, 인기의 효과를 증가 또는 감소시킬 수 있는데, 이를 factor
라 한다.
GET /blogposts/post/_search { "query": { "function_score": { "query": { "multi_match": { "query": "popularity", "fields": [ "title", "content" ] } }, "field_value_factor": { "field": "votes", "modifier": "log1p", "factor": 2 } } } }
Adding in a factor
changes the formula to this:
factor
를 추가하면, 수식은 아래와 같이 변경된다.
new_score = old_score * log(1 + factor * number_of_votes)
A factor
greater than 1
increases the effect, and a factor
less than 1
decreases the effect, as shown in Figure 31, “여러 가지 factor에 따른 인기의 log 그래프”.
Figure 31, “여러 가지 factor에 따른 인기의 log 그래프”에서 알 수 있듯이, factor
가 1
보다 크면 효과는 증가하고, 1
보다 작으면 감소한다.
boost_modeedit
Perhaps multiplying the full-text score by the result of the field_value_factor
function still has too large an effect. We can control how the result of a function is combined with the _score
from the query by using the boost_mode
parameter, which accepts the following values:
full-text score를 field_value_factor
function의 결과와 곱하면, 효과가 너무 커질 수 있다. boost_mode
매개변수를 사용하여, function의 결과가 query의 _score
와 조합되는 방법을 제어할 수 있다. 아래와 같은 값이 있다.
multiply
Multiply the
_score
with the function result (default)_score
를 function의 결과와 곱한다. (기본값)sum
Add the function result to the
_score
_score
에 function의 결과를 더한다.min
The lower of the
_score
and the function result_score
와 function의 결과 중 더 작은 값max
The higher of the
_score
and the function result_score
와 function의 결과 중 더 큰 값replace
Replace the
_score
with the function result_score
를 function의 결과로 대체한다.
If, instead of multiplying, we add the function result to the _score
, we can achieve a much smaller effect, especially if we use a low factor
:
곱하는 대신에, function의 결과에 _score
를 더한다면, 특히나 낮은 factor
를 사용한다면, 훨씬 더 작은 효과를 만들 수 있다.
GET /blogposts/post/_search { "query": { "function_score": { "query": { "multi_match": { "query": "popularity", "fields": [ "title", "content" ] } }, "field_value_factor": { "field": "votes", "modifier": "log1p", "factor": 0.1 }, "boost_mode": "sum" } } }
The formula for the preceding request now looks like this (see Figure 32, “sum
을 사용한 인기의 조합”):
이제, 위의 request에 대한 수식은 아래와 같다(Figure 32, “sum
을 사용한 인기의 조합”) 참조).
new_score = old_score + log(1 + 0.1 * number_of_votes)
max_boostedit
Finally, we can cap the maximum effect that the function can have by using the max_boost
parameter:
마지막으로, max_boost
매개변수를 사용하여, function이 가질 수 있는 최대 효과를 제한할 수 있다.
GET /blogposts/post/_search { "query": { "function_score": { "query": { "multi_match": { "query": "popularity", "fields": [ "title", "content" ] } }, "field_value_factor": { "field": "votes", "modifier": "log1p", "factor": 0.1 }, "boost_mode": "sum", "max_boost": 1.5 } } }
The max_boost
applies a limit to the result of the function only, not to the final _score
.
max_boost
는, 최종적인 _score
가 아닌, function의 결과에 대한 제한에만 적용한다.
'2.X > 2. Search in Depth' 카테고리의 다른 글
2-6-06. Ignoring TF/IDF (0) | 2017.09.24 |
---|---|
2-6-07. function_score Query (0) | 2017.09.24 |
2-6-09. Boosting Filtered Subsets (0) | 2017.09.24 |
2-6-10. Random Scoring (0) | 2017.09.24 |
2-6-11. The Closer, The Better (0) | 2017.09.24 |