As you all might be aware of the elasticsearch in nature – it is more like a persistent database system. Now during development or production, there always can come a need for changing the mapping / structure. Now adding a field to mapping is not a problem but changing a field can be a problem for sure. As elasticsearch dose not allow us to change the field type mapping on the fly. So – how to achieve the same? Let us go with the original scenario we were working with dealing in earlier (topic / topic_name) problem set.
Original Structure
{
"mappings": {
"words": {
"properties": {
"platform": {
"type": "keyword"
},
"topic": {
"type": "keyword"
},
"topic_id": {
"type": "integer"
},
"topic_name": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
}
}
}
Now if you realize in the above structure the field topic_name is a new field that got created, now we simply wanted to map it as a field with type – keyword. Also, we want to remove the field topic from the mapping.
How to achieve the same? There is a trick to doing the same with minimal or no downtime. For the same, we need to follow the following steps:
- Create a new mapping with the required structure – but with another index name (topicsv2)
{
"mappings": {
"words": {
"properties": {
"platform": {
"type": "keyword"
},
"topic_name": {
"type": "keyword"
},
"topic_id": {
"type": "integer"
},
}
}
}
- Run a _reindex on the 2 mappings
POST /_reindex
{
"source": {
"index": "topics",
"type": "words",
"_source": {
"excludes": [
"topic"
]
}
},
"dest": {
"index": "topicsv2",
"type": "words"
}
}
In the script above – you will notice one thing – we have asked elastic to exclude the specific field which we don’t want elasticsearch to copy it into the new index (topic). Now since we have managed to recreate the new index and move in all the data from previous index to new one, now what we will require to work on is still be able to manage the previous name (topics). Now how to achieve the same, elasticsearch have a powerful feature for the same i will say – Alias. How to go about using the same here?
Go ahead, delete the current mapping that we have (topics). Then create a new alias for the same
POST /_aliases
{
"actions" : [
{
"add" : {
"index" : "topicsv2", "alias" : "topics"
}
}
]
}
Now with this feature – you will be able to access the data still using topics as index and also with topicsv2.
Now with the above solution that we derived with – what i have experienced and will like to share along with fellow developer friends of mine is – will recommend using indexes with v1 / v2 (at the end of their index name) originally. And let the same be served with index names (without versions). This is best during development / production – especially while development, when we are at the peak of changing the structure as and when required / demanded. But the same scenario can also arise in the production environment too. Hence it is good to have it in there too.
Now this will definitely help you do the restructuring of the mapping with ease.