69

I am new to Elasticsearch and am currently working on implementing a geo_distance filter for searching. As of now my index has the following mapping (I've removed some fields):

{
advert_index: {
   mappings: {
      advert_type: {
         properties: {
            __v: {
               type: "long"
            },
            caption: {
               type: "string"
            },
            category: {
               type: "string"
            },
            **location: {
            type: "long"
            },**

         }
      }
   }
}

The geo_distance field is going to be implemented on the location field, where an example instance looks like this:

"location": [
               71,
               60
            ],

I.e. is on geoJSON format [lon, lat].

I understand that I will have to update my index so that the location field is of type geo_point, as described in the documentation (mapping-geo-point). It seems like I have to drop the index and create a new one, but I am not able to do this.

Am I on the right track? I would greatly appreciate it if anyone could help me with how I could create a new index or update my existing one with the correct data type.

Many thanks!

Tejus Prasad
  • 6,322
  • 7
  • 47
  • 75
Axelfran
  • 964
  • 1
  • 7
  • 17

3 Answers3

88

Generally speaking, you can update your index mapping using the put mapping api (reference here) :

curl -XPUT 'http://localhost:9200/advert_index/_mapping/advert_type' -d '
{
    "advert_type" : {
        "properties" : {

          //your new mapping properties

        }
    }
}
'

It's especially useful for adding new fields. However, in your case, you will try to change the location type, which will cause a conflict and prevent the new mapping from being used.

You could use the put mapping api to add another property containing the location as a lat/lon array, but you won't be able to update the previous location field itself.

Finally, you will have to reindex your data for your new mapping to be taken into account.

The best solution would really be to create a new index.

If your problem with creating another index is downtime, you should take a look at aliases to make things go smoothly.

matt burns
  • 24,742
  • 13
  • 105
  • 107
ThomasC
  • 7,915
  • 2
  • 26
  • 26
  • Thank you Tom for your prompt answer. How specifically would I create a new index with the correct type for location? I am currently in a development setting, so downtime etc. is not an issue. I have been using this code to create the index as of now: [link](http://stackoverflow.com/questions/23846971/how-to-use-elasticsearch-with-mongodb) (At the bottom) – Axelfran Aug 24 '14 at 13:33
  • I'm not familiar with the mongoDB river, but from what I see the river is based on the dynamic mapping (ES auto detecting the mapping to apply, based on the value). You could control this by [creating the index and its mapping manually](http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-create-index.html#mappings), and then replace ARBITRARY INDEX NAME and ARBITRARY TYPE NAME by the freshly created index name/type name. You should maybe create a new question for this as it's a separate subject. – ThomasC Aug 24 '14 at 14:00
  • 1
    The approach provided below worked like a charm. Thanks a lot! – Axelfran Aug 24 '14 at 15:49
  • Is it possible to Creta a New Index but saving the documents stored? – Ricardo Polo Jaramillo May 11 '16 at 16:59
  • 1
    Take a look at the [reindex API introduced in 2.3](https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-reindex.html) : it should do the trick :) – ThomasC May 26 '16 at 09:08
  • @ThomasC ...how to handle update going on live server while reindexing to a new index? – Prannoy Mittal Aug 29 '16 at 15:54
  • @ThomasC in case I need to start supporting sorting by date and there was no mapping for date field before, can I just update mapping? Do I need to reindex and how in this case? p.s. ES 6.x – Ewoks Jul 27 '19 at 08:47
7

In later Elasticsearch versions (7.x), types were removed. Updating a mapping can becomes:

curl -XPUT "http://localhost:9200/test/_mapping" -H 'Content-Type: application/json' -d'{
  "properties": {
    "new_geo_field": {
      "type": "geo_point"
    }
  }
}'

As others have pointed out, if the field exists, you typically have to reindex. There are exceptions, such as adding a new sub-field or changing analysis settings.

You can't "create a mapping", as the mapping is created with the index. Typically, you'd define the mapping when creating the index (or via index templates):

curl -XPUT "http://localhost:9200/test" -H 'Content-Type: application/json' -d'{
  "mappings": {
    "properties": {
      "foo_field": {
        "type": "text"
      }
    }
  }
}'

That's because, in production at least, you'd want to avoid letting Elasticsearch "guess" new fields. Which is what generated this question: geo data was read as an array of long values.

Radu Gheorghe
  • 984
  • 9
  • 6
6

Please note that there is a mistake in the url provided in this answer:

For a PUT mapping request: the url should be as follows:

http://localhost:9200/name_of_index/_mappings/document_type

and NOT

http://localhost:9200/name_of_index/document_type/_mappings

Algorini
  • 824
  • 1
  • 12
  • 19
  • 6
    This depends on which version of Elasticsearch you are using. E.g., version 0.90 used the notation which you say to be not valid: https://www.elastic.co/guide/en/elasticsearch/reference/0.90/indices-put-mapping.html – Sicco Mar 22 '16 at 18:34