Blog

2017.11.16 - 번역 - Removal of Mapping Types in Elasticsearch 6.0 ...

drscg 2019. 1. 7. 12:57

Mapping types are going away. Elasticsearch 6.0 supports a single mapping type per index only, and it represents the first step on the way to removing types altogether.

mapping type이 없어진다. Elasticsearch 6.0은 index 당 하나의 mapping type만 지원하며, 그것은 type을 완전히 제거하는 것의 첫 번째 단계이다.

This blog post explains what types are, why we are removing them, how you can migrate your indices to a single type world, and lays out the full schedule for type removal over the next three major versions.

이 블로그 게시물은 type이 무엇인지, 왜 제거하는지, indices를 단일 type으로 migration할 수 있는지, 그리고 다음 3개의 major version에 걸친, type 제거에 대한 전체 일정을 설명한다.

  • Indices created in Elasticsearch 6.0.0 or later may contain a single mapping type only.
    Elasticsearch 6.0.0 이후에 생성된 indices는 단일 mapping type만을 가진다.
  • Indices created in 5.x with multiple mapping types will continue to function as before in Elasticsearch 6.x.
    5.x에서 생성된, 여러 개의 type을 가진 indices는 Elasticsearch 6.x 이전처럼 계속 동작한다.
  • Mapping types will be completely removed in Elasticsearch 7.0.0 although some backwards compatibility features will only be removed in 9.0.0.
    일부 이전 버전 호환성 기능은 9.0.0 에서 제거될 예정이지만, mapping type은 Elasticsearch 7.0.0에서 완전히 제거된다.

What are mapping types?


Since the first release of Elasticsearch, each document has been stored in a single index and assigned a single mapping type. A mapping type was used to represent the type of document or entity being indexed, for instance a twitter index might have a user type and a tweet type.

Elasticsearch의 첫 번째 release 이후, 각 document는 단일 index에 저장되고, 단일 mapping type이 지정되었다. mapping type은 indexing되는 document 또는 entity의 type을 나타내는 데 사용되었다. 예를 들어 twitter index는 user type과 tweet type을 가질 수 있다.

Each mapping type could have its own fields, so the user type might have a full_name field, a user_name field, and an email field, while the tweet type could have a content field, a tweeted_at field and, like the user type, a user_name field.

각 mapping type은 자체 field를 가질 수 있으므로, user type은 full_name fielduser_name field 및 email field를 가질 수 있다, 반면에, tweet type은 content field, tweeted_at field, 그리고 user type과 마찬가지로 user_name 를 가질 수 있다.

Each document had a _type meta-field containing the type name, and searches could be limited to one or more types by specifying the type name(s) in the URL:

각 document에는 type name을 포함하는 _type meta-field가 있으며, URL에 type name을 지정하여 검색을 하나 이상의 type으로 제한할 수 있다.

GET twitter/user,tweet/_search { "query": { "match": { "user_name": "kimchy" } } }


The _type field was combined with the document’s _id to generate a _uid field, so documents of different types with the same _id could exist in a single index.

_type field는 document의 _id와 결합되어 _uid field를 생성하므로, 동일한 _id를 가진 다양한 type의 document가 단일 index에 존재할 수 있다.

Mapping types were also used to establish a parent-child relationship between documents, so documents of type question could be parents to documents of type answer.

또한 mapping type은 document간에 parent-child relationship을 설정하는 데 사용되므로, question 유형의 document는 answer 유형의 document에 대한 부모가 될 수 있다.

Why are mapping types being removed?


In the early days of Elasticsearch, we spoke about an “index” being similar to a “database” in an SQL database, and a “type” being equivalent to a “table”.

Elasticsearch 초기에는, SQL database의 "database" 와 유사한 "index", "table"과 같은 "type" 에 대해 이야기했다.

This was a bad analogy that led to incorrect assumptions. In an SQL database, tables are independent of each other. The columns in one table have no bearing on columns with the same name in another table. This is not the case for fields in a mapping type.

이것은 잘못된 추측으로 이어진 좋지 않은 비유였다. SQL database에서 table은 서로 독립적이다. 어떤 table의 column은 다른 table의 같은 이름을 가진 column과 관련이 없습니다. 이것은 mapping type의 field에는 해당되지 않는다.

In an Elasticsearch index, fields that have the same name in different mapping types are backed by the same Lucene field internally. In other words, using the example above, the user_name field in the user type is stored in exactly the same field as the user_name field in the tweet type, and both user_name fields must have the same mapping (definition) in both types.

Elasticsearch index에서, 다른 mapping type에 동일한 이름을 가진 field는 내부적으로 동일한 Lucene field에 저장된다. 즉, 위 예에서, user type의 user_name field는 tweet type의 user_name field와 정확히 동일한 field에 저장되며, 두 user_name field는 두 type 모두에서 동일한 mapping(정의)을 가져야 한다.

This can lead to frustration when, for example, you want deleted to be a date field in one type and a booleanfield in another type in the same index.

예를 들어, 동일한 index에서, 어떤 type에서는 deleted를 date field로 지정하고, 또 다른 type에서는 booleanfield로 지정하는 경우, 문제가 될 수 있다.

On top of that, storing different entities that have few or no fields in common in the same index leads to sparse data and interferes with Lucene’s ability to compress documents efficiently.

게다가, 동일한 index에서, 동일한 field가 거의 없거나, 전혀 다른 여러 entity을를 저장하면, date가 희소해져 효율적으로 document를 압축할 수있는 Lucene의 기능을 방해하게 된다.

For these reasons, we have decided to remove the concept of mapping types from Elasticsearch.

이러한 이유로, 우리는 Elasticsearch에서 mapping type의 개념을 제거하기로 결정했다.

Alternatives to mapping types


Custom type field


There is a limit to how many primary shards can exist in a cluster so you may not want to waste an entire shard for a collection of only a few thousand documents. In this case, you can implement your own custom type field which will work in a similar way to the old _type.

cluster에 존재할 수 있는 primary shard가 몇 개 있는지에 대한 제한이 있으므로, 수천 개의 document만 수집하는데, 전체 shard를 낭비하고 싶지는 않을 것이다. 이 경우, 기존의 _type과 유사한 방식으로 작동하는 사용자 정의 type field를 구현할 수 있다.

Let’s take the user/tweet example above. Originally, the workflow would have looked something like this:

위의 user/tweet 예제를 보자. 원래의 흐름은 다음과 같다.

PUT twitter { "mappings": { "user": { "properties": { "name": { "type": "text" }, "user_name": { "type": "keyword" }, "email": { "type": "keyword" } } }, "tweet": { "properties": { "content": { "type": "text" }, "user_name": { "type": "keyword" }, "tweeted_at": { "type": "date" } } } } } PUT twitter/user/kimchy { "name": "Shay Banon", "user_name": "kimchy", "email": "shay@kimchy.com" } PUT twitter/tweet/1 { "user_name": "kimchy", "tweeted_at": "2017-10-24T09:00:00Z", "content": "Types are going away" } GET twitter/tweet/_search { "query": { "match": { "user_name": "kimchy" } } }


You could achieve the same thing by adding a custom type field as follows:

다음과 같이 사용자 정의 type field를 추가하여, 동일한 결과를 얻을 수 있다.

PUT twitter { "mappings": { "doc": { "properties": { "type": { "type": "keyword" }, "name": { "type": "text" }, "user_name": { "type": "keyword" }, "email": { "type": "keyword" }, "content": { "type": "text" }, "tweeted_at": { "type": "date" } } } } } PUT twitter/doc/user-kimchy { "type": "user", "name": "Shay Banon", "user_name": "kimchy", "email": "shay@kimchy.com" } PUT twitter/doc/tweet-1 { "type": "tweet", "user_name": "kimchy", "tweeted_at": "2017-10-24T09:00:00Z", "content": "Types are going away" } GET twitter/_search { "query": { "bool": { "must": { "match": { "user_name": "kimchy" } }, "filter": { "match": { "type": "tweet" } } } } }


If you need to run searches and aggregations across old indices (which use the _type field) and new indices (with a custom type field), you can rewrite the query as follows:

기존의 indices(_type field를 사용한)와 새로운 indices(사용자 정의 type field를 사용한)에서, search 및 aggregation를 실행해야 하는 경우, 다음과 같이 query를 다시 작성할 수 있다.

GET twitter_old,twitter_new/_search { "query": { "bool": { "must": { "match": { "user_name": "kimchy" } }, "filter": { "bool": { "should": [ { "term": { "_type": "tweet" }}, { "term": { "type": "tweet" }} ] } } } } }


Index per document type


The other alternative is to have an index per document type. Instead of storing tweets and users in a singletwitter index, you could store tweets in the tweets index and users in the user index. Indices are completely independent of each other and so there will be no conflict of field types between indices.

또 다른 대안은 document 유형별 색인을 갖는 것입니다. tweets과 users를 단일 twitter index에 저장하는 대신, tweets index에 tweets을, user index에 users를 저장할 수 있다. indices는 서로 완전히 독립적이므로, indices간에 field type이 충돌하지 않는다.

This approach has two benefits:

이 방식은 2가지 이점이 있다.

  • Data is more likely to be dense and so benefit from compression techniques used in Lucene.
    data가 조밀할 가능성이 더 높아, Lucene에서 사용되는 압축 기술의 이점을 누릴 수 있다.
  • The term statistics used for scoring in full text search are more likely to be accurate because all documents in the same index represent a single entity.
    full text search에서 score를 계산하는데 사용되는 term statistics가, 동일한 index의 모든 document가 단일 entity를 나타내므로 더 정확하다.

Each index can be sized appropriately for the number of documents it will contain: you can use a smaller number of primary shards for users and a larger number of primary shards for tweets.

각 index는 포함할 document의 수에 맞게 크기를 적절하게 지정할 수 있다. users의 primary shard 수를 줄이고, tweets의 primary shard 수를 더 많이 사용할 수 있다.

Parent/Child without mapping types


Previously, a parent-child relationship was represented by making one mapping type the parent, and one or more other mapping types the children. Without types, we can no longer use this syntax. The parent-child feature will continue to function as before, except that the way of expressing the relationship between documents has been changed to use the new join field.

이전에는, 어떤 mapping type을 parent로 만들고, 하나 이상의 다른  mapping type을 children으로 만들어 parent-child 관계를 표현했다. type이 없으면 더 이상이 이 문법을 사용할 수 없다. parent-child 기능은 이전과 같이 계속 동작하지만, document 간의 관계 표현 방식이 새로운 join field를 사용하도록 변경되었다.

Schedule for removal of mapping types


This is a big change for our users, so we have tried to make it as painless as possible. The change will roll out as follows:

이는 사용자에게 커다란 변화이므로, 가능한 한 쉽게 만들려고 노력했다. 변경 사항은 다음과 같이 공개될 예정이다.

Elasticsearch 5.6.0
  • Setting index.mapping.single_type: true on an index enables the single-type-per-index behaviour which is enforced in 6.0.
    index에 index.mapping.single_type: true 를 설정하면, 6.0 에서 적용되는 index별 단일 type(single-type-per-index) 방식이 활성화된다.
  • The join field replacement for parent-child is available on indices created in 5.6.
    parent-child를 대체하는 join field는 5.6에서 생성된 index에서 사용할 수 있다.
Elasticsearch 6.x
  • Indices created in 5.x will continue to function in 6.x as they did in 5.x.
    5.x에서 생성된 indices는 5.x에서와 마찬가지로 6.x에서도 계속 동작한다.
  • Indices created in 6.x only allow a single-type per index. Any name can be used for the type, but there can be only one.
    6.x에서 생성된 indices는 index별 단일 type만 허용한다. type에는 어떤 이름이라도 사용할 수 있지만, 하나만 있을 수 있다.
  • The _type name can no longer be combined with the _id to form the _uid field. The _uid field has become an alias for the _id field.
    _type 이름은 더 이상_id와 결합하여 _uid field를 형성할 수 없다. _uid field는 _id field의 alias가 되었다.
  • New indices no longer support the old-style of parent/child and should use the join field instead.
    새로운 indices는 더 이상 기존 스타일의 parent/child를 지원하지 않으며, 대신에 join field를 사용해야 한다.
  • The _default_ mapping type is deprecated.
    _default_ mapping type은 deprecate되었다.
Elasticsearch 7.x
  • The type parameter in URLs are optional. For instance, indexing a document no longer requires a document type.
    URL의 type 매개변수는 선택 사항이다. 예를 들어, document indexing에는 더 이상 document type이 필요하지 않다.
  • The GET|PUT _mapping APIs support a query string parameter ( include_type_name) which indicates whether the body should include a layer for the type name. It defaults to true. 7.x indices which don’t have an explicit type will use the dummy type name _doc.
    GET|PUT _mapping API는 body에 type 이름의 layer가 포함되어야 하는지 여부를 나타내는 query string 매개변수( include_type_name)를 지원한다. 기본값은 true이다. 명시적인 type이 없는 7.x indices는 dummy type 이름인 더미 유형 이름 _doc을 사용한다.
  • The _default_ mapping type is removed.
    _default_ mapping type은 제거된다.
Elasticsearch 8.x
  • The type parameter is no longer supported in URLs.
    URL에서type 매개변수는 더 이상 지원되지 않는다.
  • The include_type_name parameter defaults to false.
    include_in_type 매개변수의 기본값은 false이다.
Elasticsearch 9.x
  • The include_in_type parameter is removed.
    include_in_type 매개변수는 제거된다.

Migrating multi-type indices to single-type


The Reindex API can be used to convert multi-type indices to single-type indices. The following examples can be used in Elasticsearch 5.6 or Elasticsearch 6.x. In 6.x, there is no need to specify index.mapping.single_type as that is the default.

Reindex API는 다중 type indices를 단일 type indices로 변환하는 데 사용될 수 있다. 다음 예제는 Elasticsearch 5.6 또는 Elasticsearch 6.x에서 사용될 수 있다. 6.x에서는 index.mapping.single_type 을 기본값으로 지정할 필요가 없다.

Custom type field


This first example adds a custom type field and sets it to the value of the original _type. It also adds the type to the _id in case there are any documents of different types which have conflicting IDs:

이 첫 번째 예제에서는, 사용자 정의 type field를 추가하고, 원래 _type의 값으로 설정한다. 또한 conflicting ID가 있는 다른 type의 document가 있는 경우, _id에 type을 추가한다.


PUT new_twitter { "mappings": { "doc": { "properties": { "type": { "type": "keyword" }, "name": { "type": "text" }, "user_name": { "type": "keyword" }, "email": { "type": "keyword" }, "content": { "type": "text" }, "tweeted_at": { "type": "date" } } } } } POST _reindex { "source": { "index": "twitter" }, "dest": { "index": "new_twitter" }, "script": { "source": """ ctx._source.type = ctx._type; ctx._id = ctx._type + '-' + ctx._id; ctx._type = 'doc'; """ } }


Index per document type


This next example splits our twitter index into a tweets index and a users index:

이 다음 예제는 twitter index를 tweets index와 users index로 나눈다.

PUT users { "settings": { "index.mapping.single_type": true }, "mappings": { "user": { "properties": { "name": { "type": "text" }, "user_name": { "type": "keyword" }, "email": { "type": "keyword" } } } } } PUT tweets { "settings": { "index.mapping.single_type": true }, "mappings": { "tweet": { "properties": { "content": { "type": "text" }, "user_name": { "type": "keyword" }, "tweeted_at": { "type": "date" } } } } } POST _reindex { "source": { "index": "twitter", "type": "user" }, "dest": { "index": "users" } } POST _reindex { "source": { "index": "twitter", "type": "tweet" }, "dest": { "index": "tweets" } }


원문 : Removal of Mapping Types in Elasticsearch 6.0