0

I tried once with alias index by moving data to new index, and I found it took too long, by following this guide https://www.elastic.co/blog/changing-mapping-with-zero-downtime.

In addition, I have around 75 millions documents,and also growing up in every second.

I tried to move data from old index to new index with elasticdump but It's very slow.

Is there any fastest way I can change type mapping?

centic
  • 15,565
  • 9
  • 68
  • 125
Tanapat Sainak
  • 734
  • 1
  • 10
  • 22

2 Answers2

2

One way to achieve this is to create another string field in your mapping and modify the existing long one with a copy_to to that new field.

curl -XPUT localhost:9200/your_index/_mapping/your_type -d '{
  "your_type": {
    "properties": {
      "long_field": {
        "type": "long",
        "copy_to": "str_field"      <---- copy_to new field
      },
      "str_field": {                <---- new field
        "type": "string",
        "store": true               <---- store it if you want to see it using fields=...
      }
    }
  }
}'

All newly indexed documents will get the new field str_field populated. You can also modify your indexing process to populate that new field directly in the source document you send to ES, of course. Note that if you don't, the str_field will only be indexed (so it can be searched) but it will not appear in the _source. You can still store str_field by adding "store": true for that field and then you'll be able to see its value when querying using &fields=str_field

For all existing documents, that field can be populated in different ways without having to re-index everything (that would defeat the purpose and you would simply create a new index instead), but with a cleverly set-up bulk re-indexing process just for that new field, that can be done.

Another hardcore solution would be to use the update-by-query plugin.

You still need to add the new str_field to your mapping, without modifying the existing one:

curl -XPUT localhost:9200/your_index/_mapping/your_type -d '{
  "your_type": {
    "properties": {
      "str_field": {                <---- new field
        "type": "string"
      }
    }
  }
}'

And then using the plugin you can issue a query such as this one that will populate the new field (and optionally remove the long_field from the source if you don't need it anymore:

curl -XPOST 'localhost:9200/your_index/_update_by_query' -d '{
    "query" : {
        "match_all" : {}
    },
    "script" : "ctx._source.str_field = String.valueOf(ctx._source.long_field); ctx._source.remove(\"long_field\"); "
}'

For that second solution, you need to make sure to enable scripting in elasticsearch.yml and restart ES:

script.inline: on 
script.indexed: on

Note, however, that with this second solution your new field will not be populated unless you also adapt your indexing process in order to include that new str_field field in the JSON documents you send to ES.

Val
  • 207,596
  • 13
  • 358
  • 360
1

You can only change the mapping by re-creating the index, there is no way to change the mapping in-place.

So you likely need to find the fastest way to export/import the data into a new index. Instead of exporting the data out of Elasticsearch and then writing it back in you can try using one of the reindexing-plugins which may be able to keep the data locally on the nodes without the cost for the data-transfer, see e.g. https://github.com/codelibs/elasticsearch-reindexing which looks promising.

centic
  • 15,565
  • 9
  • 68
  • 125