summaryrefslogtreecommitdiff
path: root/docs/reference/mapping/dynamic/templates.asciidoc
blob: eb9eb1a60d90eb33f84109b42e8e40c01a342e2f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
[[dynamic-templates]]
=== Dynamic templates

Dynamic templates allow you to define custom mappings that can be applied to
dynamically added fields based on:

* the <<dynamic-mapping,datatype>> detected by Elasticsearch, with <<match-mapping-type,`match_mapping_type`>>.
* the name of the field, with <<match-unmatch,`match` and `unmatch`>> or <<match-pattern,`match_pattern`>>.
* the full dotted path to the field, with <<path-match-unmatch,`path_match` and `path_unmatch`>>.

The original field name `{name}` and the detected datatype
`{dynamic_type`} <<template-variables,template variables>> can be used in
the mapping specification as placeholders.

IMPORTANT: Dynamic field mappings are only added when a field contains a
concrete value -- not `null` or an empty array. This means that if the
`null_value` option  is used in a `dynamic_template`, it will only be applied
after the first document  with a concrete value for the field has been
indexed.

Dynamic templates are specified as an array of named objects:

[source,js]
--------------------------------------------------
  "dynamic_templates": [
    {
      "my_template_name": { <1>
        ...  match conditions ... <2>
        "mapping": { ... } <3>
      }
    },
    ...
  ]
--------------------------------------------------
<1> The template name can be any string value.
<2> The match conditions can include any of : `match_mapping_type`, `match`, `match_pattern`, `unmatch`, `path_match`, `path_unmatch`.
<3> The mapping that the matched field should use.


Templates are processed in order -- the first matching template wins. New
templates can be appended to the end of the list with the
<<indices-put-mapping,PUT mapping>> API.  If a new template has the same
name as an existing template, it will replace the old version.

[[match-mapping-type]]
==== `match_mapping_type`

The `match_mapping_type` matches on the datatype detected by
<<dynamic-field-mapping,dynamic field mapping>>, in other words, the datatype
that Elasticsearch thinks the field should have.  Only the following datatypes
can be automatically detected: `boolean`, `date`, `double`, `long`, `object`,
`string`.  It also accepts `*` to match all datatypes.

For example, if we wanted to map all integer fields as `integer` instead of
`long`, and all `string` fields as both `text` and `keyword`, we
could use the following template:

[source,js]
--------------------------------------------------
PUT my_index
{
  "mappings": {
    "my_type": {
      "dynamic_templates": [
        {
          "integers": {
            "match_mapping_type": "long",
            "mapping": {
              "type": "integer"
            }
          }
        },
        {
          "strings": {
            "match_mapping_type": "string",
            "mapping": {
              "type": "text",
              "fields": {
                "raw": {
                  "type":  "keyword",
                  "ignore_above": 256
                }
              }
            }
          }
        }
      ]
    }
  }
}

PUT my_index/my_type/1
{
  "my_integer": 5, <1>
  "my_string": "Some string" <2>
}

--------------------------------------------------
// CONSOLE
<1> The `my_integer` field is mapped as an `integer`.
<2> The `my_string` field is mapped as a `text`, with a `keyword` <<multi-fields,multi field>>.


[[match-unmatch]]
==== `match` and `unmatch`

The `match` parameter uses a pattern to match on the fieldname, while
`unmatch` uses a pattern to exclude fields matched by `match`.

The following example matches all `string` fields whose name starts with
`long_` (except for those which end with `_text`) and maps them as `long`
fields:


[source,js]
--------------------------------------------------
PUT my_index
{
  "mappings": {
    "my_type": {
      "dynamic_templates": [
        {
          "longs_as_strings": {
            "match_mapping_type": "string",
            "match":   "long_*",
            "unmatch": "*_text",
            "mapping": {
              "type": "long"
            }
          }
        }
      ]
    }
  }
}

PUT my_index/my_type/1
{
  "long_num": "5", <1>
  "long_text": "foo" <2>
}
--------------------------------------------------
// CONSOLE
<1> The `long_num` field is mapped as a `long`.
<2> The `long_text` field uses the default `string` mapping.

[[match-pattern]]
==== `match_pattern`

The `match_pattern` parameter adjusts the behavior of the `match` parameter
such that it supports full Java regular expression matching on the field name
instead of simple wildcards, for instance:

[source,js]
--------------------------------------------------
  "match_pattern": "regex",
  "match": "^profit_\d+$"
--------------------------------------------------

[[path-match-unmatch]]
==== `path_match` and `path_unmatch`

The `path_match` and `path_unmatch` parameters work in the same way as `match`
and `unmatch`, but operate on the full dotted path to the field, not just the
final name, e.g. `some_object.*.some_field`.

This example copies the values of any fields in the `name` object to the
top-level `full_name` field, except for the `middle` field:

[source,js]
--------------------------------------------------
PUT my_index
{
  "mappings": {
    "my_type": {
      "dynamic_templates": [
        {
          "full_name": {
            "path_match":   "name.*",
            "path_unmatch": "*.middle",
            "mapping": {
              "type":       "text",
              "copy_to":    "full_name"
            }
          }
        }
      ]
    }
  }
}

PUT my_index/my_type/1
{
  "name": {
    "first":  "Alice",
    "middle": "Mary",
    "last":   "White"
  }
}
--------------------------------------------------
// CONSOLE

[[template-variables]]
==== `{name}` and `{dynamic_type}`

The `{name}` and `{dynamic_type}` placeholders are replaced in the `mapping`
with the field name and detected dynamic type.  The following example sets all
string fields to use an <<analyzer,`analyzer`>> with the same name as the
field, and disables <<doc-values,`doc_values`>> for all non-string fields:

[source,js]
--------------------------------------------------
PUT my_index
{
  "mappings": {
    "my_type": {
      "dynamic_templates": [
        {
          "named_analyzers": {
            "match_mapping_type": "string",
            "match": "*",
            "mapping": {
              "type": "text",
              "analyzer": "{name}"
            }
          }
        },
        {
          "no_doc_values": {
            "match_mapping_type":"*",
            "mapping": {
              "type": "{dynamic_type}",
              "doc_values": false
            }
          }
        }
      ]
    }
  }
}

PUT my_index/my_type/1
{
  "english": "Some English text", <1>
  "count":   5 <2>
}
--------------------------------------------------
// CONSOLE
<1> The `english` field is mapped as a `string` field with the `english` analyzer.
<2> The `count` field is mapped as a `long` field with `doc_values` disabled

[[template-examples]]
==== Template examples

Here are some examples of potentially useful dynamic templates:

===== Structured search

By default elasticsearch will map string fields as a `text` field with a sub
`keyword` field. However if you are only indexing structured content and not
interested in full text search, you can make elasticsearch map your fields
only as `keyword`s. Note that this means that in order to search those fields,
you will have to search on the exact same value that was indexed.

[source,js]
--------------------------------------------------
PUT my_index
{
  "mappings": {
    "my_type": {
      "dynamic_templates": [
        {
          "strings_as_keywords": {
            "match_mapping_type": "string",
            "mapping": {
              "type": "keyword"
            }
          }
        }
      ]
    }
  }
}
--------------------------------------------------

===== `text`-only mappings for strings

On the contrary to the previous example, if the only thing that you care about
on your string fields is full-text search, and if you don't plan on running
aggregations, sorting or exact search on your string fields, you could tell
elasticsearch to map it only as a text field (which was the default behaviour
before 5.0):

[source,js]
--------------------------------------------------
PUT my_index
{
  "mappings": {
    "my_type": {
      "dynamic_templates": [
        {
          "strings_as_text": {
            "match_mapping_type": "string",
            "mapping": {
              "type": "text"
            }
          }
        }
      ]
    }
  }
}
--------------------------------------------------

===== Disabled norms

Norms are index-time scoring factors. If you do not care about scoring, which
would be the case for instance if you never sort documents by score, you could
disable the storage of these scoring factors in the index and save some space.

[source,js]
--------------------------------------------------
PUT my_index
{
  "mappings": {
    "my_type": {
      "dynamic_templates": [
        {
          "strings_as_keywords": {
            "match_mapping_type": "string",
            "mapping": {
              "type": "text",
              "norms": false,
              "fields": {
                "keyword": {
                  "type": "keyword",
                  "ignore_above": 256
                }
              }
            }
          }
        }
      ]
    }
  }
}
--------------------------------------------------

The sub `keyword` field appears in this template to be consistent with the
default rules of dynamic mappings. Of course if you do not need them because
you don't need to perform exact search or aggregate on this field, you could
remove it as described in the previous section.

===== Time-series

When doing time series analysis with elasticsearch, it is common to have many
numeric fields that you will often aggregate on but never filter on. In such a
case, you could disable indexing on those fields to save disk space and also
maybe gain some indexing speed:

[source,js]
--------------------------------------------------
PUT my_index
{
  "mappings": {
    "my_type": {
      "dynamic_templates": [
        {
          "unindexed_longs": {
            "match_mapping_type": "long",
            "mapping": {
              "type": "long",
              "index": false
            }
          }
        },
        {
          "unindexed_doubles": {
            "match_mapping_type": "double",
            "mapping": {
              "type": "float", <1>
              "index": false
            }
          }
        }
      ]
    }
  }
}
--------------------------------------------------
<1> Like the default dynamic mapping rules, doubles are mapped as floats, which
    are usually accurate enough, yet require half the disk space.


[[override-default-template]]
=== Override default template

You can override the default mappings for all indices and all types
by specifying a `_default_` type mapping in an index template
which matches all indices.

For example, to disable the `_field_names` field by default for all types in all
new indices, you could create the following index template:

[source,js]
--------------------------------------------------
PUT _template/disable_field_names
{
  "order": 0,
  "index_patterns": ["*"], <1>
  "mappings": {
    "_default_": { <2>
      "_field_names": { <3>
        "enabled": false
      }
    }
  }
}
--------------------------------------------------
// CONSOLE
<1> Applies the mappings to an `index` which matches the pattern `*`, in other
    words, all new indices.
<2> Defines the `_default_` type mapping types within the index.
<3> Disables the `_field_names` field by default.