Blog

2016.09.07 - 번역 - Strings are dead, long live strings! ...

drscg 2019. 1. 7. 10:24

Text vs. keyword

With the release of Elasticsearch 5.0 coming closer, it is time to introduce one of the release highlights of this upcoming release: the removal of the string type. The background for this change is that we think the string type is confusing: Elasticsearch has two very different ways to search strings. You can either search whole values, that we often refer to as keyword search, or individual tokens, that we usually refer to as full-text search. If you are familiar with Elasticsearch, you know the former strings should be mapped as a not_analyzed string while the latter should be mapped as an analyzed string.

Elasticsearch 5.0 의  출시가 가까워 지면서, 이번 release의 highlight 중 하나인 string type의 제거를 소개하겠다. 이러한 변경의 배경은 string type이 혼란을 가져온다고 생각하기 때문이다. Elasticsearch는 string을 search하는 매우 다른 2가지 방법을 가지고 있다. 일반적으로 keyword search라고 하는 전체 값을 search하거나 일반적으로 full-text search라 하는 개별 token을 search할 수 있다. Elasticsearch에 익숙한 경우, 전자는 not_analyzed string으로 mapping해야 하고, 반면에 후자는 analyzed string 으로 mapping해야 한다.

But the fact that the same field type is used for these two very different use-cases is causing problems since some options only make sense for one of the use case. For instance, position_increment_gap makes little sense for a not_analyzed string and it is not obvious whether ignore_above applies to the whole value or to individual tokens in the case of an analyzed string (in case you wonder: it does apply to the whole value, limits on individual tokens can be applied with the limit token filter).

그러나, 이들 2가지 매우 다른 곳에 동일한 field type이 사용된다는 사실때문에 문제를 일으킨다. 일부 option은 하나의 경우에만 의미가 있기 때문이다. 예를 들자면, position_increment_gap 은 not_analyzed string에 거의 의미가 없으며, analyzed string의 경우 ignore_above 가 전체 값이나 개별 token에 적용되는지 여부가 명확하지 않다. (전체 값에 적용되는 경우, 개별 token에 대한 제한은 li token filter에 적용될 수 있다)

To avoid these issues, the string field has split into two new types: text, which should be used for full-text search, and keyword, which should be used for keyword search.

이런 문제를 피하기 위해, string filed를 2개의 새로운 type인, full-text search에 사용되는 text 와 keyword search에 사용되는 keyword 로 나누었다.

New defaults

At the same time we did this split, we decided to change the default dynamic mappings for string fields. When getting started with Elasticsearch, a common frustration is that you have to reindex in order to be able to aggregate on whole field values. For instance imagine you are indexing documents with a city field. Aggregating on this field would give different counts for new and york instead of having a single count for New York which is usually the expected behaviour. Unfortunately, fixing this problem requires to reindex the field in order for the index to have the correct structure to answer this question.

이렇게 나누는 것과 동시에, string에 대한 기본 dynamic mapping을 변경하였다. Elasticsearch를 시작할 때, 가장 일반적인 불만은 전체 field 값을 aggregation을 할 수 있도록 하기 위해서는 reindex를 해야 한다는 점이다. 예를 들어, city field를 가진 document를 index한다고 가정해 보자. 이 field에 대한 aggregation은 일반적으로 기대하는 동작인 New York 에 대한 단일 count 대신 new 와 york 에 대해 각각 count를 제공한다. 불행히도, 이 문제를 수정하기 위해서는 이 문제에 답하기 위해, 올바른 구조를 가지는 index를 위해, field를 reindex해야 한다. 

To make things better, Elasticsearch decided to borrow an idea that initially stemmed from Logstash: strings will now be mapped both as text and keyword by default. For instance, if you index the following simple document:

상황을 개선하기 위해, Elasticsearch는 Logstash에서 처음 나온 아이디어를 빌리기로 결정했다. string은 이제 기본적으로 text 와 keyword 양쪽 모두로 mapping된다. 다음의 간단한 document를 index하는 경우,

{
  "foo": "bar"
}

Then the following dynamic mappings will be created:

다음과 같은 dynamic mapping이 생성된다.

{
  "foo": {
    "type" "text",
    "fields": {
      "keyword": {
        "type": "keyword",
        "ignore_above": 256
      }
    }
  }
}

As a consequence, it will both be possible to perform full-text search on foo, and keyword search and aggregations using the foo.keyword field.

따라서, foo 에서 full-text search가, foo.keyword field를 사용하여 keyword search나 aggregation이 모두 가능하다.

Disabling this feature is easy: all you need to do is to either map string fields explicitly or to use a dynamic template that matches all string fields. For instance the below dynamic template can be used to restore the same dynamic mappings that were used in Elasticsearch 2.x:

이 기능을 비활성화하는 것은 쉽다. string field를 명시적으로 mapping하거나 모든 string field와 일치하는 dynamic template만 사용하면 된다. 예를 들어, 아래 dynamic template을 사용하여 Elasticsearch 2.x에서 사용된 것과 동일한 dynamic mapping으로 복원할 수 있다.

{
  "match_mapping_type": "string",
  "mapping": {
    "type": "text"
  }
}

How to migrate

In most cases, the migration should be pretty straightforward. Fields that used to be mapped as an analyzedstring

대부분의 경우, migration은 매우 간단해야 한다. analyzed string으로 mapping되어 사용되던 field는

{
  "foo": {
    "type" "string",
    "index": "analyzed"
  }
}

Now need to be mapped as a text field:

이제, text field로 mapping되어야 한다.

{
  "foo": {
    "type" "text",
    "index": true
  }
}

And fields that used to be mapped as a not_analyzed string

그리고, not_analyzed string으로 mapping되어 사용되던 field는

{
  "foo": {
    "type" "string",
    "index": "not_analyzed"
  }
}

Now need to be mapped as a keyword field:

이제, keyword field로 mapping되어야 한다.

{
  "foo": {
    "type" "keyword",
    "index": true
  }
}

As you can see, now that string fields have split into text and keyword, we do not need to have 3 states for the index property (analyzednot_analyzed and no), which only existed because of string fields. We can use a simple boolean in order to tell Elasticsearch whether searching the field should be possible.

보시다시피, 이제 string field는 text 와 keyword 로 나누어졌다. 따라서, string field 때문에 존재했던 index property에 대한 3가지 상태( analyzednot_analyzedno )는 필요하지 않다. Elasticsearch에서 filed를 search하는 것이 가능하도록 하기 위해, 단순히 boolean을 사용할 수 있다.

Backward compatibility

Because major upgrades usually have their own challenges, we did our best not require you to upgrade all mappings at the same time as you upgrade your cluster to Elasticsearch 5.0. First, the string field will keep working on existing 2.x indices. And when it comes to new indices, Elasticsearch has some logic that will make it automatically convert string mappings to an equivalent text or keyword mapping. This is especially useful if you have index templates that add mappings with string fields: these templates will keep working with Elasticsearch 5.x. That said, you should still look into upgrading them since we plan on removing this backward compatibility layer when we release Elasticsearch 6.0.

major upgrade에서는 일반적으로 자체적인 문제가 있기 때문에, Elasticsearch 5.0 으로 cluster를 upgrade할 때, 일시에 모든 mapping을 upgrade할 필요는 없다. 먼저, string field는 기존 2.x index에서 계속 동작한다. 그리고, 새로운 index를 생성 시에, Elasticsearch는 string mapping을 동등한 text 나 keyword mapping으로 자동으로 변경하는 약간의 logic을 가지고 있다. 이는 string field를 가진 mapping을 추가하는 index tempate을 가지고 있다면 특히 유용하다. 이 template은 Elasticsearch 5.0 에서 계속 동작한다. Elasticsearch 6.0 을 출시할 때, 이에 대한 이전 버전 호환성을 제거할 계획이므로, upgrade를 고려해야 한다.

원문 : Strings are dead, long live strings!