2.X/2. Search in Depth

2-3-06. Most Fields

drscg 2017. 9. 30. 00:43

Full-text search is a battle between recall—returning all the documents that are relevant—and precision—not returning irrelevant documents. The goal is to present the user with the most relevant documents on the first page of results.

full-text 검색은 recall(적합한 document 모두를 반환하는)과 정확성(precision)(부적합한 document를 반환하지 않는)의 전쟁이다. 결과의 첫 번째 page에 가장 적합한 document를 사용자에게 제시하는 것이 목표이다.

To improve recall, we cast the net wide—we include not only documents that match the user’s search terms exactly, but also documents that we believe to be pertinent to the query. If a user searches for "quick brown fox", a document that contains fast foxes may well be a reasonable result to return.

recall을 향상시키기 위해, 검색 범위를 넓게 잡는다. 사용자가 검색한 단어와 정확히 일치하는 document만 포함하는 것이 아니라, query에 관련된 것으로 생각되는 document도 포함시킨다. 사용자가 "quick brown fox" 를 검색했다면, fast foxes 를 포함하는 document도 반환할 적절한 결과가 될 것이다.

If the only pertinent document that we have is the one containing fast foxes, it will appear at the top of the results list. But of course, if we have 100 documents that contain the words quick brown fox, then the fast foxes document may be considered less relevant, and we would want to push it further down the list. After including many potential matches, we need to ensure that the best ones rise to the top.

관련 있는 document가, fast foxes 를 포함하는 document 하나뿐이면, 그것은 결과 목록의 상단에 나타날 것이다. 하지만 물론, quick brown fox 를 포함하는 document가 100개라면, fast foxes 를 포함하는 document는 덜 관련되어 있는 document로 간주될 것이고, 목록의 더 아래로 밀어낼 것이다. 일치할 가능성이 있는 많은 document를 포함시킨 후에, 가장 일치하는 document가 상위에 있는지 보장해야 한다.

A common technique for fine-tuning full-text relevance is to index the same text in multiple ways, each of which provides a different relevance signal. The main field would contain terms in their broadest-matching form to match as many documents as possible. For instance, we could do the following:

full-text relevance의 미세 조정을 위한 일반적인 기술은, 동일한 문장(text)을 여러 가지 방식으로 색인하는 것이고, 그 각각의 방식은 다른 relevance 신호(signal) 를 제공한다. 주 field는, 가능한 한 많은 document를 일치시키기 위해, 광범위하게 일치(broadest-matching)하는 형태의 단어를 포함할 것이다. 예를 들면

  • Use a stemmer to index jumpsjumping, and jumped as their root form: jump. Then it doesn’t matter if the user searches for jumped; we could still match documents containing jumping.

    jumpsjumpingjumped 를 기본형(jump)으로 색인 하기 위해, 형태소 분석기를 사용한다. 사용자가 jumped 를 검색하더라도, jumping 을 포함하는 document는 여전히 일치해야 한다.

  • Include synonyms like jumpleap, and hop.

    jumpleaphop 와 같은 동의어를 포함한다.

  • Remove diacritics, or accents: for example, éstaestá, and esta would all be indexed without accents as esta.

    발음 구별 부호나 accents를 제거한다. 예를 들면 éstaestáesta 는, accents 없이, 모두 esta 로 색인된다.

However, if we have two documents, one of which contains jumped and the other jumping, the user would probably expect the first document to rank higher, as it contains exactly what was typed in.

그런데, 두 개의 document를 가지고 있는데, 하나는 jumped 를, 다른 하나는 jumping 을 포함하고 있다면, 아마도 사용자는 자신이 입력한 것을 정확히 포함하는, 첫 번째 document가 먼저 나올 거라 예상할 것이다.

We can achieve this by indexing the same text in other fields to provide more-precise matching. One field may contain the unstemmed version, another the original word with diacritics, and a third might use shingles to provide information about word proximity. These other fields act as signalsthat increase the relevance score of each matching document. The more fields that match, the better.

보다 정확한 일치를 위해, 동일한 문장(text)을 서로 다른 field에 색인하여, 이것을 할 수 있다. 하나의 field에는 형태소 분석을 하지 않은 버전을, 다른 field에는 발음기호를 포함한 원래의 단어를 포함하고, 그리고 또 다른 field는 단어의 근접성에 대한 정보를 제공하기 위해 사용한다. 이러한 다른 field들은, 일치하는 각 document의 relevance score를 증가시키기 위한 신호(signal) 로 동작한다. 일치하는 field가 많을수록 더 좋다.

A document is included in the results list if it matches the broad-matching main field. If it also matches the signal fields, it gets extra points and is pushed up the results list.

document가 광범위하게 일치(broad-matching)하는 주 field와 일치하면, 결과 목록에 포함된다. 만약, signal field와도 일치하면, 추가 점수를 얻어, 결과 목록의 위쪽에 위치한다.

We discuss synonyms, word proximity, partial-matching and other potential signals later in the book, but we will use the simple example of stemmed and unstemmed fields to illustrate this technique.

이 책의 뒷부분에서, 동의어, 단어 근접성, 부분 일치, 그리고 다른 가능성 있는 signal에 대해 이야기 할 것이다. 이 기술을 설명하기 위해, 형태소 분석을 한 field, 형태소 분석을 하지 않은 field의 간단한 예제를 사용할 것이다.

Multifield Mappingedit

The first thing to do is to set up our field to be indexed twice: once in a stemmed form and once in an unstemmed form. To do this, we will use multifields, which we introduced in String Sorting and Multifields:

먼저, field를 두 가지 방식(한 번은 형태소 분석을 한 형태, 또 한번은 형태소 분석을 하지 않은 형태)으로 색인하도록 설정해야 한다. 이를 위해, String Sorting and Multifields에서 소개한, 다중 field(multifields) 를 사용할 것이다.

DELETE /my_index

PUT /my_index
{
    "settings": { "number_of_shards": 1 }, 
    "mappings": {
        "my_type": {
            "properties": {
                "title": { 
                    "type":     "string",
                    "analyzer": "english",
                    "fields": {
                        "std":   { 
                            "type":     "string",
                            "analyzer": "standard"
                        }
                    }
                }
            }
        }
    }
}

Relevance Is Broken!를 참고하자.

title field는 english analyzer에 의해 형태소 분석된다.

title.std field는 standard analyzer를 사용하고, 형태소 분석을 하지 않는다.

Next we index some documents:

다음 단계로, 몇 개의 document를 색인하자.

PUT /my_index/my_type/1
{ "title": "My rabbit jumps" }

PUT /my_index/my_type/2
{ "title": "Jumping jack rabbits" }

Here is a simple match query on the title field for jumping rabbits:

title field에서 jumping rabbits 을 검색하는, 간단한 match query가 아래에 있다.

GET /my_index/_search
{
   "query": {
        "match": {
            "title": "jumping rabbits"
        }
    }
}

This becomes a query for the two stemmed terms jump and rabbit, thanks to the english analyzer. The title field of both documents contains both of those terms, so both documents receive the same score:

english analyzer로 인해, 형태소 분석된 두 단어 jumprabbit 으로 검색하게 된다. 두 document의 title field는 이들 단어 모두를 포함하고 있어서, 두 document는 동일한 score를 가진다.

{
  "hits": [
     {
        "_id": "1",
        "_score": 0.42039964,
        "_source": {
           "title": "My rabbit jumps"
        }
     },
     {
        "_id": "2",
        "_score": 0.42039964,
        "_source": {
           "title": "Jumping jack rabbits"
        }
     }
  ]
}

If we were to query just the title.std field, then only document 2 would match. However, if we were to query both fields and to combine their scores by using the bool query, then both documents would match (thanks to the title field) and document 2 would score higher (thanks to the title.std field):

title.std field로만 query하면, document 2만 일치한다. 그러나 두 field 모두에게 query를 하면, boolquery를 사용하여 score를 조합 한다. 그리고 나면 두 document 모두 일치할 것이고(title field 덕분에), document 2는 더 높은 score를 가질 것이다(title.std field 덕분에).

GET /my_index/_search
{
   "query": {
        "multi_match": {
            "query":  "jumping rabbits",
            "type":   "most_fields", 
            "fields": [ "title", "title.std" ]
        }
    }
}

모두 일치하는 field로부터 score를 조합하려면, most_fields 형식을 사용해야 한다. 이것은, multi_match query가 dis_max query 대신에 bool query로 두 개의 field 절을 감싸기 때문이다.

{
  "hits": [
     {
        "_id": "2",
        "_score": 0.8226396, 
        "_source": {
           "title": "Jumping jack rabbits"
        }
     },
     {
        "_id": "1",
        "_score": 0.10741998, 
        "_source": {
           "title": "My rabbit jumps"
        }
     }
  ]
}

 

이제 score가 document 2가 document 1 보다 더 높다.

We are using the broad-matching title field to include as many documents as possible—to increase recall—but we use the title.std field as a signal to push the most relevant results to the top.

가능한 한 많은 document를 포함하기 위해(recall을 증가시키기 위해), 광범위하게 일치하는 title field를 사용하고 있다. 그러나, 우리는 title.std field를 가장 적합한 결과를 상위로 올리기 위한 signal 로 사용한다.

The contribution of each field to the final score can be controlled by specifying custom boost values. For instance, we could boost the title field to make it the most important field, thus reducing the effect of any other signal fields:

최종 score에 대한 각 field에 대한 기여도는, boost 값을 지정하여 조정한다. 예들 들어, title field를 가장 중요한 field로 만들기 위해, 가중치를 부여할 수 있는데, 이렇게 하면 다른 signal field의 효과는 감소한다.

GET /my_index/_search
{
   "query": {
        "multi_match": {
            "query":       "jumping rabbits",
            "type":        "most_fields",
            "fields":      [ "title^10", "title.std" ] 
        }
    }
}

title field의 boost 값 10 은 해당 field를 title.std field보다 상대적으로 훨씬 더 중요한 field로 만든다.


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

2-3-04. Tuning Best Fields Queries  (0) 2017.09.30
2-3-05. multi_match Query  (0) 2017.09.30
2-3-07. Cross-fields Entity Search  (0) 2017.09.30
2-3-08. Field-Centric Queries  (0) 2017.09.28
2-3-09. Custom _all Fields  (0) 2017.09.28