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 제거에 대한 전체 일정을 설명한다.
- What are mapping types?
type이 무엇인가? - Why are mapping types being removed?
왜 mapping type이 제거되는가? - Alternatives to mapping types
mapping type의 대안- Custom type field
사용자 정의 type field - Index per document type
document 유형별 index
- Custom type field
- Parent/Child without mapping types
mapping type 없는 parent/child - Schedule for removal of mapping types
mapping type의 제거 일정 - Migrating multi-type indices to single-type
다수의 type을 가진 indices를 단일 type으로 migration- Custom type field
사용자 정의 type field - Index per document type
document 유형별 index
- Custom type field
- 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 field, user_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 boolean
field in another type in the same index.
예를 들어, 동일한 index에서, 어떤 type에서는 deleted를 date
field로 지정하고, 또 다른 type에서는 boolean
field로 지정하는 경우, 문제가 될 수 있다.
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에서 사용할 수 있다.
- Setting
- 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되었다.
- Indices created in 5.x will continue to function in 6.x as they did in 5.x.
- Elasticsearch 7.x
- The
type
parameter in URLs are optional. For instance, indexing a document no longer requires a documenttype
.
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 totrue
. 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은 제거된다.
- The
- Elasticsearch 8.x
- The
type
parameter is no longer supported in URLs.
URL에서type
매개변수는 더 이상 지원되지 않는다. - The
include_type_name
parameter defaults tofalse
.include_in_type
매개변수의 기본값은false
이다.
- The
- Elasticsearch 9.x
-
- The
include_in_type
parameter is removed.include_in_type
매개변수는 제거된다.
- The
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" } }