Updating a mapping in ElasticSearch

Assumption: we have an index things with a mapping m1 and the result we want is an index with the same name and the same data but a different mapping m2. For instance, there might be a string field in m1 that we want to turn into an indexed date field.

  1. Create a backup of the current index just in case
    • PUT /things-bak
    • POST /_reindex { "source": { "index": "things" }, "dest": { "index": "things-bak" } }
  2. Update the mapping in the index template with the new field
    • GET /_template/things-template
    • peel the outer layer by piping through jq '.things'
    • modify the mapping
    • update the template with the modified mapping
      • PUT /_template/things-template <template_json>
    • at that point, we have only updated the template, things still uses the old mapping which we can check with GET /things/_mapping
  3. Create a new index with the right name, so that it matches the index pattern from the template. Assuming we have a pattern like "template": "things*", things-v2 would work.
    • PUT /things-v2
    • at that point, we have a new index with the new mapping, but it’s empty.
    • verify that the new index has the new mapping with GET /things-v2/_mapping
  4. Reindex the data from the old to the new index
    • POST /_reindex { "source": { "index": "things" }, "dest": { "index": "things-v2" } }
  5. Check that the new index has the data with GET /index-v2/_search?pretty
  6. At this point, there are 2 options:
    1. DELETE /things, PUT /things (it has the new mapping now), reindex things-v2 into things and DELETE /things-v2 (phew)
    2. or simply DELETE /things and create an alias to the new index: POST /_aliases { "actions" : [ { "add" : { "index" : "things-v2", "alias" : "things" } } ] }
Written on November 30, 2017