2.X/2. Search in Depth

2-4-3. Multivalue Fields

drscg 2017. 9. 24. 21:54

A curious thing can happen when you try to use phrase matching on multivalue fields. Imagine that you index this document:

다중 값(multi-value) field에 구문 일치를 사용하는 경우, 특이한 상황이 발생할 수 있다. 아래 document를 색인한다고 가정해 보자.

PUT /my_index/groups/1
{
    "names": [ "John Abraham", "Lincoln Smith"]
}

Then run a phrase query for Abraham Lincoln:

그 다음에, Abraham Lincoln 에 대한 phrase query를 실행해 보자.

GET /my_index/groups/_search
{
    "query": {
        "match_phrase": {
            "names": "Abraham Lincoln"
        }
    }
}

Surprisingly, our document matches, even though Abraham and Lincoln belong to two different people in the names array. The reason for this comes down to the way arrays are indexed in Elasticsearch.

Abraham 과 Lincoln 이, names 배열에서, 다른 두 사람에 포함되어 있는데도 불구하고, document는 일치한다. 그 이유는 배열이 Elasticsearch에 색인되는 방법에 있다.

When John Abraham is analyzed, it produces this:

John Abraham 은 다음과 같이 분석된다.

  • Position 1: john
  • Position 2: abraham

Then when Lincoln Smith is analyzed, it produces this:

Lincoln Smith 는 다음과 같이 분석된다.

  • Position 3: lincoln
  • Position 4: smith

In other words, Elasticsearch produces exactly the same list of tokens as it would have for the single string John Abraham Lincoln Smith. Our example query looks for abraham directly followed by lincoln, and these two terms do indeed exist, and they are right next to each other, so the query matches.

다시 말하면, Elasticsearch는 하나의 문자열 John Abraham Lincoln Smith 을 분석한 것과, 정확히 동일한 단어 목록을 만들어낸다. 예제 query는 abraham 에 바로 이어서 lincoln 이 나오는 경우를 찾는다. 그리고, 이들 두 단어가 확실히 존재하고, 그들이 서로 바로 옆에 있으면, query는 일치한다.

Fortunately, there is a simple workaround for cases like these, called the position_increment_gap, which we need to configure in the field mapping:

다행히, 이런 경우에 대한 간단한 해결책이 있다. position_increment_gap 이라는 것인데, field mapping에서 설정해야 한다.

DELETE /my_index/groups/ 

PUT /my_index/_mapping/groups 
{
    "properties": {
        "names": {
            "type":                "string",
            "position_increment_gap": 100
        }
    }
}

먼저 groups mapping과 해당 type의 모든 document를 모두 삭제한다.

그 다음에, 올바른 값으로 groups 라는 새로운 mapping을 생성한다.

The position_increment_gap setting tells Elasticsearch that it should increase the current term position by the specified value for every new array element. So now, when we index the array of names, the terms are emitted with the following positions:

position_increment_gap 설정은, 모든 새로운 배열 요소에 대해, 지정된 값만큼, 현재 단어의 위치(position) 를 증가시킨다. 그래서 names 배열을 색인할 때, 단어들은 다음과 같은 위치를 출력한다.

  • Position 1: john
  • Position 2: abraham
  • Position 103: lincoln
  • Position 104: smith

Our phrase query would no longer match a document like this because abraham and lincoln are now 100 positions apart. You would have to add a slop value of 100 in order for this document to match.

phrase query는, abraham 과 lincoln 이 이제 100만큼 떨어져 있기 때문에, 더 이상 일치하지 않을 것이다. 이 document가 일치하도록 하려면, slop 에 100을 추가하면 된다.

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

2-4-1. Phrase Matching  (0) 2017.09.24
2-4-2. Mixing It Up  (0) 2017.09.24
2-4-4. Closer Is Better  (0) 2017.09.24
2-4-5. Proximity for Relevance  (0) 2017.09.24
2-4-6. Improving Performance  (0) 2017.09.24