Reputation: 121
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
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
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
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
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