I'm providing a default mapping dynamic template at index creation in elasticsearch and wanted to check if it works as expected. Got me stumped, how can I verify if it works?
(Working with ES 2.2.2)
"mappings": {
"_default_": {
"dynamic_templates": [
{
"no_date_detection": {
"match_mapping_type": "string",
"mapping": {
"type": "string",
"date_detection": false
}
}
},
{
"language_de": {
"match_mapping_type": "*",
"match": "*_de",
"mapping": {
"type": "string",
"analyzer": "german"
}
}
},
{
"language_es": {
"match": "*_es",
"match_mapping_type": "*",
"mapping": {
"type": "string",
"analyzer": "spanish"
}
}
},
{
"language_en": {
"match": "*_en",
"match_mapping_type": "*",
"mapping": {
"type": "string",
"analyzer": "english"
}
}
}
]
}
}
It's pretty straightforward, like in the examples provided in the documentation.
GETting the mapping shows that the dynamic templates are handed down to new types
"testobject": {
"dynamic_templates": [
{
"no_date_detection": {
"mapping": {
"type": "string",
"date_detection": false
},
"match_mapping_type": "string"
}
},
{
"language_de": {
...
But when I create an object with new fields like
"description_en": "some english text"
and GET the mapping it just shows
"description_en": {
"type": "string"
}
Shouldn't this have
"analyzer": "english"
in it?
What did I do wrong, and if my dynamic mapping is correct, how can I verify that it gets applied?
Thanks in advance /Carsten
As my question "how can I verify that it gets applied?" seems unclear, I try to simplify:
I create an index with default dynamic mapping.
I create a type "testobject".
"GET /myindex/testobject/_mappings" verifies that, as expected, the dynamic templates are handed down to the type.
I create a new field in an object of type testobject.
"GET /myindex/testobject/_mappings" shows the new field but without say '"date_detection": false'. It shows it just as a simple string (see above).
How can I verify if/that the dynamic template got applied to a newly created field?
Simplified example:
PUT /myindex
{
"mappings": {
"_default_": {
"dynamic_templates": [
{
"no_date_detection": {
"match_mapping_type": "string",
"mapping": {
"type": "string",
"date_detection": false
}
}
}
]
}
}
}
PUT /myindex/gardeners/1
{
"name": "gary"
}
GET /myindex/_mapping
{
"myindex": {
"mappings": {
"gardeners": {
"dynamic_templates": [
{
"no_date_detection": {
"mapping": {
"type": "string",
"date_detection": false
},
"match_mapping_type": "string"
}
}
],
"properties": {
"name": {
"type": "string"
}
}
},
"_default_": {
"dynamic_templates": [
{
"no_date_detection": {
"mapping": {
"type": "string",
"date_detection": false
},
"match_mapping_type": "string"
}
}
]
}
}
}
}
The mapping for my new field "name"
"properties": {
"name": {
"type": "string"
}
}
doen't contain
"date_detection": false
Why doesn't it get handed down?
The dynamic templates are checked in the order they are defined and the first one that matches, that's the one that gets applied.
In your case no_date_detection template matches your field description_en because it's a string.
If you want that field to be used with the english analyzer, then you need to change the order of the templates:
"mappings": {
"_default_": {
"dynamic_templates": [
{
"language_de": {
"match_mapping_type": "*",
"match": "*_de",
"mapping": {
"type": "string",
"analyzer": "german"
}
}
},
{
"language_es": {
"match": "*_es",
"match_mapping_type": "*",
"mapping": {
"type": "string",
"analyzer": "spanish"
}
}
},
{
"language_en": {
"match": "*_en",
"match_mapping_type": "*",
"mapping": {
"type": "string",
"analyzer": "english"
}
}
},
{
"no_date_detection": {
"match_mapping_type": "string",
"mapping": {
"type": "string",
"date_detection": false
}
}
}
]
}
}
I found the error in my assumption: "date_detection": false doesn't work that way with dynamic_templates.
You have to specify the date_detection directly on the mapping (not at the level of a specific type).
https://www.elastic.co/guide/en/elasticsearch/guide/current/custom-dynamic-mapping.html
If you want this to get automatically added to new indices, you can use index templates.
Thanks to Yannick for the hint (https://discuss.elastic.co/t/mappings--default--dynamic-templates-doesnt-show-up-in-resulting-mapping/59030)
Related
I am new to elasticseach and trying to implement small assignment for my own learning prospect.
I am referring https://www.elastic.co/guide/en/elasticsearch/reference/current/dynamic-templates.html link to create a dynamic template; however while running the query mentioned below I am getting "type" : "mapper_parsing_exception", "reason" : "Root mapping definition has unsupported parameters: error .
Can someone please assist me with the error? looks like I haven't defined my template name in proper place .
PUT e_review_dynamictemplate
{
"mappings": {
"date_detection": true,
"dynamic_date_formats": ["dd/MM/yyyy"],
"numeric_detection": true,
"My_dynamic_templates": [
{
"e_full_name": {
"path_match": "*_Name",
"mapping": {
"type": "text",
"copy_to": "e_full_name",
"norms": false
}
},
"integers": {
"match_mapping_type": "long",
"mapping": {
"type": "integer",
"index": false
}
},
"strings": {
"match_mapping_type": "string",
"match": "Achievements:*",
"unmatch": "Improvements:*",
"mapping": {
"type": "long"
}
}
}
]
}
}
Thanks in advance!
Nivedita
you just missed the dynamic_templates properties in the mappings object. You just have to replace My_dynamic_templates by dynamic_templates.
The custom names are used in template definitions inside the dynamic_templates array.
Here is the corrected snippet :
PUT e_review_dynamictemplate
{
"mappings": {
"date_detection": true,
"dynamic_date_formats": [
"dd/MM/yyyy"
],
"numeric_detection": true,
"dynamic_templates": [
{
"e_full_name": {
"path_match": "*_Name",
"mapping": {
"type": "text",
"copy_to": "e_full_name",
"norms": false
}
}
},
{
"integers": {
"match_mapping_type": "long",
"mapping": {
"type": "integer",
"index": false
}
}
},
{
"strings": {
"match_mapping_type": "string",
"match": "Achievements:*",
"unmatch": "Improvements:*",
"mapping": {
"type": "long"
}
}
}
]
}
}
hi i am using elasticsearch to index some documents. but the documents will have some fileds like goal1Completion, goal2Completion....goal100Completion. so i was trying to do mapping with dynamic Templates. so i came up with following but it throws an error:
{
"mappings": {
"date": {
"properties": {
"sessions": {
"type": "long"
},
"viewId": {
"type": "string",
"index": "not_analyzed"
},
"webPropertyId": {
"type": "string",
"index": "not_analyzed"
},
"dynamic_templates": [
{
"goalCompletions": {
"match_pattern": "regex",
"match": "goal\\d+\\w+",
"mapping": {
"type": "long"
}
}
}
]
}
}
}
}
error:"reason": "Expected map for property [fields] on field [dynamic_templates] but got a class java.lang.String"
what could be thee problem here?
You need to pull dynamic_template from properties map.
{
"mappings": {
"date": {
"properties": {
"sessions": {
"type": "long"
},
"viewId": {
"type": "string",
"index": "not_analyzed"
},
"webPropertyId": {
"type": "string",
"index": "not_analyzed"
}
},
"dynamic_templates": [ <--- Pull this out of properties
{
"goalCompletions": {
"match_pattern": "regex",
"match": "goal\\d+\\w+",
"mapping": {
"type": "long"
}
}
}
]
}
}
}
I wanted to setup mapping so that any unknown field of type float automatically got the property index=false.
I used the following request:
PUT /myindex/_mapping/mytype
{
"dynamic_templates": [
{ "quantity": {
"match": "*",
"match_mapping_type": "float",
"mapping": {
"index": "false"
}
}}
],
"properties": {
"ELEMENT_ID": {
"type": "long",
"index": "true"
},
"ELEMENT_TYPE": {
"type": "keyword",
"index": "true"
}
}
}
However the unknown fields remain searchable:
GET /myindex/mytype/_search
{
"query": {
"term": { "FEEDBACK_I": "0.8202897" }
}
}
Is it possible to achieve this?
Thanks!
I suggest this approach instead (ES is more likely to match your float to a double). And, also, index property has an allowed value of no in 1.x and 2.x and true/false in 5.x:
PUT /myindex/mytype/_mapping
{
"mytype": {
"dynamic_templates": [
{
"quantity": {
"match": "*",
"match_mapping_type": "double",
"mapping": {
"type": "double",
"index": "no"
}
}
},
{
"quantity_float": {
"match": "*",
"match_mapping_type": "float",
"mapping": {
"type": "float",
"index": "no"
}
}
}
]
}
}
I tried to do:
PUT /index_name/
{ "index" : {
"analysis" : {
"analyzer" :"not_analyzed"
}
}
}
but I'm not sure it is the right way...
Edit:
I applied both methods from the answers. But I have no way to test it. If in fact it do
GET /index_name/_mapping
...
"metaData_requestHeaders_accept-language": {
"type": "string"
},
"metaData_requestHeaders_akamai-origin-hop": {
"type": "string"
},
"metaData_requestHeaders_alexatoolbar-alx_ns_ph": {
"type": "string"
},
"metaData_requestHeaders_authorization": {
"type": "string"
},
"metaData_requestHeaders_c": {
"type": "string"
},
"metaData_requestHeaders_cache-control": {
"type": "string"
},
"metaData_requestHeaders_ckiooe": {
"type": "string"
},
...
as you can see the automatic mapping does not show what analyzer is used. So I have no way to test that this is actually working. Any ideas?
Use Dynamic Templates like :
PUT my_index
{
"mappings": {
"my_type": {
"dynamic_templates": [
{
"strings": {
"match_mapping_type": "string",
"mapping": {
"type": "string",
"index": "not_analyzed"
}
}
}
]
}
}
}
After applying above template you should see something like this :
GET /my_index/_mapping
{
"my_index": {
"mappings": {
"my_type": {
"dynamic_templates": [
{
"strings": {
"mapping": {
"index": "not_analyzed",
"type": "string"
},
"match_mapping_type": "string"
}
}
],
"properties": {}
}
}
}
}
Above mapping indicate that all strings will be not_analyzed by default.
I guess what you're looking for is Elasticsearch Templates, that allow you to create mappings dynamically.
You want something like this:
PUT index_name
{
"mappings": {
"type_name": {
"dynamic_templates": [
{
"strings": {
"match_mapping_type": "string",
"mapping": {
"type": "string",
"fields": {
"raw": {
"type": "string",
"index": "not_analyzed"
}
}
}
}
}
]
}
}
}
I have an ElasticSearch type for which I want the mapping to be set dynamically. There are a few select fields on that type that I want to be analyzed, but everything else should be set to "not_analyzed".
I've come up with the following snippet. This sets all string fields to not be analyzed, but doesn't cover all other data types. I tried using the "generic" field shown in the documentation but it didn't help. Can anyone tell me how I can accomplish this?
{
"TypeName": {
"dynamic_templates": [
{
"template_name": {
"match": "*",
"match_mapping_type": "string",
"mapping": {
"index": "no",
"type": "string"
}
}
}
],
"dynamic": true,
"properties": {
"url": {
"index": "analyzed",
"type": "string"
},
"resourceUrl": {
"index": "analyzed",
"type": "string"
}
}
}
}
{
"mappings": {
"TypeName": {
"dynamic_templates": [
{
"base": {
"mapping": {
"index": "not_analyzed"
},
"match": "*",
"match_mapping_type": "*"
}
}
],
"dynamic": true,
"properties": {
"url": {
"index": "analyzed",
"type": "string"
},
"resourceUrl": {
"index": "analyzed",
"type": "string"
}
}
}
}
}
Overall, index-level template:
{
"mappings": {
"_default_": {
"dynamic_templates": [
{
"base": {
"mapping": {
"index": "not_analyzed"
},
"match": "*",
"match_mapping_type": "*"
}
}
]
}
}
}