In the previous chapters, we discussed how to create index mappings and index the data. But what if you already have the mappings created, data indexed, but you want to modify the structure of the index? This is possible to some extent and soon we will learn how to do it.
Let's assume that we have the following mappings for our users
index stored in the user.json
file:
{ "user" : { "properties" : { "name" : {"type" : "string", "store" : "yes", "index" : "analyzed"} } } }
This is nothing unusual, just a simple type that stores the username. Let's create our index and let's create the type with the preceding mappings:
curl -XPOST 'localhost:9200/users' curl -XPUT 'localhost:9200/users/user/_mapping' -d @user.json
If everything went well, we will have our index and type created. So now let's try adding a new field to the mappings.
Let's assume that we want to add a new field that will store our user's phone number so we can show it in our application. In order to do that, we need to send an HTTP PUT command to the /index_name/type_name/_mapping
REST endpoint with the proper body that will include our new field. For example, to add the phone
field, we would run the following command:
curl -XPUT 'http://localhost:9200/users/user/_mapping' -d ' { "user" : { "properties" : { "phone" : {"type" : "string", "store" : "yes", "index" : "not_analyzed"} } } }'
Once again, everything went well and we have a new field added to our index structure.
After adding a new field to the existing type, we need to index all the documents again, because ElasticSearch didn't update them automatically. This is crucial to remember. You can use your primary source of data to do that or use the _source
field to get the original data from it and index it once again.
So now our index structure contains two fields, namely, the name
and phone
fields. We have indexed some data, but after a while, we decide that we want to search the phone
field, and we would like to change its index
property from not_analyzed
to analyzed
. So we run the following command:
curl -XPUT 'http://localhost:9200/users/user/_mapping' -d ' { "user" : { "properties" : { "phone" : {"type" : "string", "store" : "yes", "index" : "analyzed"} } } }'
And ElasticSearch returns the following:
{"error":"MergeMappingException[Merge failed with failures {[mapper [phone] has different index values, mapper [phone] has different index_analyzer, mapper [phone] has different search_analyzer]}]","status":400}
This is because we can't change the not_analyzed
field to analyzed
. And not just that, in most cases, you won't be able to update the field's mapping.
For example, the following modification can be safely made:
multi_field
typeThe following modifications are prohibited or will not work:
If you want to ignore conflicts and just make the new mappings, you can set the ignore_conflicts
parameter to true
. This will cause ElasticSearch to overwrite your mappings with the one you send. So our previous command with the additional parameter would look like this:
curl -XPUT 'http://localhost:9200/users/user/_mapping?ignore_conflicts=true' -d '...'