Elasticsearch Mapping Management + Templates
Mapping Management + Templates
As described earlier, a mapping defines the shape of a field key. Once a mapping has been created, it cannot be modified except by adding fields. To change it, you need to recreate the index.
There are four ways to create or add mappings.
- Create mappings automatically
- Create mappings manually
- Create mappings with templates
- Add fields to an existing mapping
Create mappings automatically
Elasticsearch automatically creates mappings when creating documents in an index, as shown below.
Create a document in the mapping_test index
PUT /mapping_test/_doc/1
{
"date":"2021/12/01 09:00:00+0900",
"Tweet":"This is a mapping test."
}
Check the mapping
GET /mapping_test
Mapping contents
GET /mapping_test
{
"mapping_test" : {
"aliases" : { },
"mappings" : {
"properties" : {
"Tweet" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"date" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
}
}
},
// ... omitted ...
From the result above, you can see that the following mappings were defined. The difference between the text and keyword types is as follows.
- The
dateandTweetkeys aretexttype. - The
date.keywordandtext.keywordkeys arekeywordtype.
The date key in the mapping above is registered as text, but there are cases where it should be registered as the date type. In that case, you need to create the mapping manually.
Create mappings manually
Manual mapping creation is done as follows.
Create a manual mapping
PUT /mapping_test2
{
"mappings": {
"properties": {
"date": {
"type": "date",
"format": "yyyy/MM/dd HH:mm:ssZ"
},
"tweet": {
"type": "text",
"fields": {
"keyword":{
"type":"keyword"
}
}
}
}
}
}
Result of creating the mapping manually
GET /mapping_test2
Manually created mapping contents
GET /mapping_test2
{
"mapping_test2" : {
"aliases" : { },
"mappings" : {
"properties" : {
"date" : {
"type" : "date",
"format" : "yyyy/MM/dd HH:mm:ssZ"
},
"tweet" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword"
}
}
}
}
},
... omitted ...
If it was created correctly, you can see that the date key is mapped as the date type.
When the format differs from the one specified in the mapping
If you create a document with a format different from the one specified in the mapping, an error occurs.
When running the following example, the date field format is "yyyy/MM/dd HH:mm:ssZ", but the data is inserted with the different format "yyyy/MM/dd HH:mm:Z" because seconds are not specified.
Create a document with a format different from the mapping
PUT /mapping_test2/_doc/1
{
"date":"2021/12/01 09:00+0900",
"tweet":"This is a mapping test."
}
Error message
{
"error" : {
"root_cause" : [
{
"type" : "mapper_parsing_exception",
"reason" : "failed to parse field [date] of type [date] in document with id '1'. Preview of field's value: '2021/12/01 09:00+0900'"
}
],
... omitted ...
As expected, the message says that the date field cannot be parsed.
When the format matches the mapping
Now create a document with the correct format.
Create a document according to the mapping format
PUT /mapping_test2/_doc/2
{
"date":"2020/11/01 09:00:00+0900",
"tweet":"This is a mapping test."
}
When the document is created with the correct format, you can see that it succeeds.
Create mappings with templates
Creating the same mapping for each index is cumbersome. Templates solve this problem.
When an index with the specified name is created, a template creates the index using the template mapping. Use the template API to create a template.
Use the _template API.
PUT /_template/test_template
{
"index_patterns": "test*",
"mappings": {
"properties": {
"date": {
"type": "date",
"format": "yyyy/MM/dd HH:mm:ssZ"
},
"tweet": {
"type": "text",
"fields": {
"keyword":{
"type":"keyword"
}
}
}
}
}
}
In the template above, because "index_patterns": "test*" is specified, the mapping is created for index names that have "test" as a prefix.
Now check how the template works.
Create the test index
PUT /test
Check the mapping of the test index
GET /test
Check the mapping result of the test index
GET /test
{
"test" : {
"aliases" : { },
"mappings" : {
"properties" : {
"date" : {
"type" : "date",
"format" : "yyyy/MM/dd HH:mm:ssZ" // date field registered with the format specified in the template
},
"tweet" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword"
}
}
}
}
},
... omitted ...
You can see that the date field was registered with the format specified in the template.
Add fields to an existing mapping
Use the mapping API to add a new field to an existing mapping.
Here, add the additional_field field to the mapping of the mapping_test2 index.
Contents of mapping_test2
GET /mapping_test2
{
"mapping_test2" : {
"aliases" : { },
"mappings" : {
"properties" : {
"date" : {
"type" : "date",
"format" : "yyyy/MM/dd HH:mm:ssZ"
},
"tweet" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword"
}
}
}
}
},
... omitted ...
Add a format to the mapping
PUT /mapping_test2/_mapping
{
"properties":{
"additional_field":{
"type":"text"
}
}
}
Check that the additional_field format was added
GET /mapping_test2
Result confirming that the additional_field format was added
{
"mapping_test2" : {
"aliases" : { },
"mappings" : {
"properties" : {
"additional_field" : { // additional_field was added
"type" : "text"
},
"date" : {
"type" : "date",
"format" : "yyyy/MM/dd HH:mm:ssZ"
},
"tweet" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword"
}
}
}
}
},
... omitted ...
You can confirm that the additional_field field was added.