Modifying your index structure with the update API

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.

The mapping

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.

Adding a new field

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.

Note

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.

Modifying fields

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:

  • Updating a field to the multi_field type
  • Adding a new type definition
  • Adding a new field
  • Adding a new analyzer

The following modifications are prohibited or will not work:

  • Changing the type of the field (for example, from text to numeric)
  • Changing "stored to field" to "not stored" and vice versa
  • Changing the value of the indexed property
  • Changing the analyzer of an already indexed document

Note

Please remember that the aforementioned examples of allowed and not allowed modifications do not mention all the possibilities of update API usage, and you have to try it for yourself to see if the update you are trying to carry out will 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 '...'
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset