user3618259
user3618259

Reputation: 121

Configure elasticsearch mapping with java api

I have a few elasticsearch fields that I don't want to analyze before indexing. I have read that the right way to do this is by altering the index mapping. Right now my mapping looks like this:

{
  "test" : {
   "general" : {
      "properties" : {
        "message" : {
          "type" : "string"
        },
        "source" : {
          "type" : "string"
        }
      }
    }
  }
}

And I would like it to look like this:

{
  "test" : {
   "general" : {
      "properties" : {
        "message" : {
          "type" : "string",
          "index" : "not_analyzed"
        },
        "source" : {
          "type" : "string"
        }
      }
    }
  }
}

I have been trying to change the settings via

client.admin().indices().prepareCreate("test")
        .setSettings(getGrantSettings());

Where getGrantSettings() looks like:

static Settings getGrantSettings(){
    JSONObject settingSource = new JSONObject();
    try{
        settingSource.put("mapping", new JSONObject()
        .put("message", new JSONObject()
            .put("type", "string")
            .put("index", "not_analyzed")
        ));
    } catch (JSONException e){
        e.printStackTrace();
    }


    Settings set = ImmutableSettings.settingsBuilder()
            .loadFromSource(settingSource.toString()).build();
    return set;
}

Upvotes: 11

Views: 24633

Answers (4)

bAZtARd
bAZtARd

Reputation: 22

So, turns out elasticsearch docs are way outdated on that topic. not_analyzed does not exist anymore and string is now text. After some trial and error I came up with this:

CreateIndexRequest createIndexRequest = new CreateIndexRequest("yourIndexName");
XContentBuilder mapping = jsonBuilder()
                .startObject()
                  .startObject("properties")
                    .startObject("yourProperty")
                      .field("type", "keyword")
                    .endObject()
                  .endObject()
                .endObject();
createIndexRequest.mapping("yourEntityName", mapping);
client.indices().create(createIndexRequest);

Now yourProperty can be queried for exact value only with term query.

Upvotes: 0

neun24
neun24

Reputation: 233

Just read the Definitive Guide carefully:

Although you can add to an existing mapping, you can’t change existing field mappings. If a mapping already exists for a field, data from that field has probably been indexed. If you were to change the field mapping, the indexed data would be wrong and would not be properly searchable.

Source: https://www.elastic.co/guide/en/elasticsearch/guide/current/mapping-intro.html#updating-a-mapping

So you just have to do it when you create the field. Thats why the code from this answer works without problems.

Upvotes: 0

Charith De Silva
Charith De Silva

Reputation: 3740

Adding this for future readers. Please note you need to perform mapping prior to create the actual index or you will get an exception. See following code.

client.admin().indices().create(new CreateIndexRequest("indexname")).actionGet();

PutMappingResponse putMappingResponse = client.admin().indices()
    .preparePutMapping("indexname")
    .setType("indextype")
    .setSource(jsonBuilder().prettyPrint()
                .startObject()
                    .startObject("indextype")
                        .startObject("properties")
                            .startObject("country").field("type", "string").field("index", "not_analyzed").endObject()
                        .endObject()
                    .endObject()
                .endObject())
    .execute().actionGet();

IndexResponse response1 = client.prepareIndex("indexname", "indextype")
    .setSource(buildIndex())
    .execute()
    .actionGet();   

// Now "Sri Lanka" considered to be a single country :) 
SearchResponse response = client.prepareSearch("indexname"
    ).addAggregation(AggregationBuilders.terms("countryfacet").field("country")).setSize(30).execute().actionGet(); 

Upvotes: 11

Paige Cook
Paige Cook

Reputation: 22555

I have successfully applied mappings to an Elasticsearch index using the Java API like the following:

 XContentBuilder mapping = jsonBuilder()
                              .startObject()
                                   .startObject("general")
                                        .startObject("properties")
                                            .startObject("message")
                                                .field("type", "string")
                                                .field("index", "not_analyzed")
                                             .endObject()
                                             .startObject("source")
                                                .field("type","string")
                                             .endObject()
                                        .endObject()
                                    .endObject()
                                 .endObject();

  PutMappingResponse putMappingResponse = client.admin().indices()
                .preparePutMapping("test")
                .setType("general")
                .setSource(mapping)
                .execute().actionGet();

Hope this helps.

Upvotes: 20

Related Questions