2.X/2. Search in Depth

2-3-03. Best Fields

drscg 2017. 9. 30. 00:52

Imagine that we have a website that allows users to search blog posts, such as these two documents:

사용자들이 블로그 포스트를 검색할 수 있는 website를 가지고 있다고 가정해 보자. 다음과 같이 2개의 document가 있다.

PUT /my_index/my_type/1
{
    "title": "Quick brown rabbits",
    "body":  "Brown rabbits are commonly seen."
}

PUT /my_index/my_type/2
{
    "title": "Keeping pets healthy",
    "body":  "My quick brown fox eats rabbits on a regular basis."
}

The user types in the words "Brown fox" and clicks Search. We don’t know ahead of time if the user’s search terms will be found in the title or the body field of the post, but it is likely that the user is searching for related words. To our eyes, document 2 appears to be the better match, as it contains both words that we are looking for.

사용자가 "Brown fox" 라는 말을 입력하고 Search를 클릭했다. 우리는 사용자가 검색한 용어가 게시물의 title field에 있는지, body field에 있는지, 사전에 알지 못하지만, 사용자는 관련 단어를 검색할 가능성이 높다. 보기에는, 검색하고 있는 단어 2개 모두를 포함하고 있는, document 2가 더 일치하는 것으로 보인다.

Now we run the following bool query:

이제 다음과 같은 bool query를 실행한다.

{
    "query": {
        "bool": {
            "should": [
                { "match": { "title": "Brown fox" }},
                { "match": { "body":  "Brown fox" }}
            ]
        }
    }
}

And we find that this query gives document 1 the higher score:

그러면, 이 query가 document 1에 더 높은 score를 주고 있음을 알 수 있다.

{
  "hits": [
     {
        "_id":      "1",
        "_score":   0.14809652,
        "_source": {
           "title": "Quick brown rabbits",
           "body":  "Brown rabbits are commonly seen."
        }
     },
     {
        "_id":      "2",
        "_score":   0.09256032,
        "_source": {
           "title": "Keeping pets healthy",
           "body":  "My quick brown fox eats rabbits on a regular basis."
        }
     }
  ]
}

To understand why, think about how the bool query calculates its score:

왜 이런 결과가 나오는지 이해하기 위해서는, bool query가 score를 계산하는 방법에 대해 생각해 봐야 한다.

  1. It runs both of the queries in the should clause.

    should 절의 두 개의 query를 모두 실행한다.

  2. It adds their scores together.

    그 score를 모두 더한다.

  3. It multiplies the total by the number of matching clauses.

    그 합을 일치하는 절의 수로 곱한다.

  4. It divides the result by the total number of clauses (two).

    결과를 전체 절의 수(2)로 나눈다.

Document 1 contains the word brown in both fields, so both match clauses are successful and have a score. Document 2 contains both brown and fox in the body field but neither word in the titlefield. The high score from the body query is added to the zero score from the title query, and multiplied by one-half, resulting in a lower overall score than for document 1.

document 1은 두 field 모두 brown 이라는 단어를 가지고 있기 때문에, 두 match 절은 모두 성공하고 score를 가진다. document 2는 body field에 brownfox 모두가 있지만, title field에는 둘 다 없다. body query에서 얻은 높은 score와 title query에서 얻은 score 0을 더한다. 그리고 1/2를 곱한다. 그 결과, 전체 score는 document 1 보다 더 낮다.

In this example, the title and body fields are competing with each other. We want to find the single best-matching field.

이 예제에서, title 과 body field는 서로 경쟁한다. 가장 일치(best-matching) 하는 field 하나를 찾으려 한다.

What if, instead of combining the scores from each field, we used the score from the best-matchingfield as the overall score for the query? This would give preference to a single field that contains both of the words we are looking for, rather than the same word repeated in different fields.

각 field로부터 얻은 score를 조합하는 대신에, 가장 일치(best-matching) 하는 field에서 얻은 score를, query에 대한 전체 score로 사용한다면 어떻게 될까? 이는 다른 field에서 동일한 단어를 반복하기 보다, 검색하고 있는 단어 모두 를 포함하고 있는 하나의 field에 우선 순위를 주는 것이다.

dis_max Queryedit

Instead of the bool query, we can use the dis_max or Disjunction Max Query. Disjunction means or(while conjunction means and) so the Disjunction Max Query simply means return documents that match any of these queries, and return the score of the best matching query:

bool query 대신, dis_max(Disjunction Max Query)를 사용할 수 있다. disjunction은 or 를 의미한다. 반면에 conjunction은 and 를 의미한다. 따라서, dis_max는 이들 중 어떤 query라도 일치하는 document를 반환하고, 가장 일치(best matching)하는 query의 score를 반환하는 것 을 의미한다.

{
    "query": {
        "dis_max": {
            "queries": [
                { "match": { "title": "Brown fox" }},
                { "match": { "body":  "Brown fox" }}
            ]
        }
    }
}

This produces the results that we want:

아래는 위 query의 결과이다.

{
  "hits": [
     {
        "_id":      "2",
        "_score":   0.21509302,
        "_source": {
           "title": "Keeping pets healthy",
           "body":  "My quick brown fox eats rabbits on a regular basis."
        }
     },
     {
        "_id":      "1",
        "_score":   0.12713557,
        "_source": {
           "title": "Quick brown rabbits",
           "body":  "Brown rabbits are commonly seen."
        }
     }
  ]
}


'2.X > 2. Search in Depth' 카테고리의 다른 글

2-3-01. Multiple Query Strings  (0) 2017.09.30
2-3-02. Single Query String  (0) 2017.09.30
2-3-04. Tuning Best Fields Queries  (0) 2017.09.30
2-3-05. multi_match Query  (0) 2017.09.30
2-3-06. Most Fields  (0) 2017.09.30