Chapter 09 · Dynamic Templates, Index Templates, Component Templates, and Schema Evolution
Dynamic Templates by Path/Name/Type for Stable Mapping Contracts
Use ordered dynamic-template rules to map fields by detected type, field name, and dotted path while keeping flexible AtlasMart metadata inside a governed search contract.
Learning outcomes
AtlasMart must accept a bounded set of merchant extensions without letting every merchant invent a new global schema. Dynamic templates provide conditional mapping rules, but they are code: order, match scope and output type determine the permanent mapping created when the first concrete value arrives.
Design dynamic-template rules using match_mapping_type, match/unmatch and path_match/path_unmatch.
Explain first-match ordering and why a broad rule placed too early can shadow a precise rule.
Keep product-owned fields explicit while exposing a constrained merchant extension namespace.
Validate template behavior by indexing boundary fixtures and inspecting mapping/field capabilities.
Recognize where Elasticsearch and OpenSearch dynamic-template features diverge and keep the portable core narrow.
The reproducible examples target self-managed Elasticsearch 9.5.3 and OpenSearch 3.8.0 using the existing AtlasMart local-course conventions: Elasticsearch on https://localhost:9200 with its copied CA certificate, OpenSearch on https://localhost:9201 with the disposable demo certificate explicitly treated as local-only, and no moving latest tags. Template and mapping syntax is verified against current official documentation. Both products support the core dynamic-template matching family used in the mandatory lab. Elasticsearch also documents runtime-field dynamic-template options; OpenSearch has different dynamic-mode extensions. Treat product-specific output mappings as separate artifacts when portability matters.
The generation environment does not run the two search servers, so commands are specified as deterministic labs and expected invariants rather than represented as captured live output. Run them only against the disposable AtlasMart course indices/templates, record the actual API responses from your pinned versions, and never test alias cutover or destructive cleanup against production names.
1. A dynamic template is an ordered conditional mapping rule
| Selector | Question it answers | AtlasMart use |
|---|---|---|
| match_mapping_type | What JSON/detected type did the parser see? | Only boolean merchant flags receive boolean mapping. |
| match / unmatch | What is the leaf field name? | Fields ending in _label become keyword. |
| path_match / path_unmatch | What is the full dotted field path? | Only merchant.codes.* becomes keyword. |
| match_pattern | Should name/path patterns use simple wildcard or regex semantics? | Use the simplest pattern sufficient for the contract. |
| mapping | What permanent mapping is created when this rule wins? | keyword/text/boolean/etc with explicit options. |
Template arrays are ordered. Design from most specific to most general and test overlaps deliberately. A broad string rule that appears first can capture a field intended for a later merchant-code rule.
2. Build a constrained AtlasMart extension surface
DELETE atlasmart-products-dynamic-v1
PUT atlasmart-products-dynamic-v1
{
"settings": {"number_of_shards":1,"number_of_replicas":0},
"mappings": {
"dynamic": true,
"dynamic_templates": [
{
"merchant_flags": {
"path_match": "merchant.flags.*",
"match_mapping_type": "boolean",
"mapping": {"type":"boolean"}
}
},
{
"merchant_codes": {
"path_match": "merchant.codes.*",
"match_mapping_type": "string",
"mapping": {"type":"keyword","ignore_above":128}
}
},
{
"labels_by_name": {
"match": "*_label",
"match_mapping_type": "string",
"mapping": {"type":"keyword","ignore_above":128}
}
},
{
"other_strings": {
"match_mapping_type": "string",
"mapping": {
"type":"text",
"fields":{"keyword":{"type":"keyword","ignore_above":256}}
}
}
}
],
"properties": {
"product_id":{"type":"keyword"},
"price":{"type":"scaled_float","scaling_factor":100}
}
}
}
PUT atlasmart-products-dynamic-v1/_doc/P-9101?refresh=true
{
"product_id":"P-9101",
"price":129.95,
"campaign_label":"autumn",
"merchant": {
"flags":{"fragile":true},
"codes":{"warehouse":"THR-07"}
},
"description":"Wireless headset"
}
GET atlasmart-products-dynamic-v1/_mapping
GET atlasmart-products-dynamic-v1/_field_caps?fields=campaign_label,merchant.flags.*,merchant.codes.*,description*
The acceptance test is type-level evidence:
campaign_label is aggregatable as keyword;
merchant.codes.warehouse is keyword;
merchant.flags.fragile is boolean; and
description follows the fallback text-plus-keyword
contract. Do not accept “indexing returned 201” as sufficient
proof.
3. Demonstrate the ordering bug
WRONG order:
1. any string -> text + keyword
2. merchant.codes.* string -> keyword
The first matching rule wins, so merchant.codes.warehouse becomes text+keyword.
CORRECT order:
1. merchant.codes.* string -> keyword
2. narrow name/path rules
3. general string fallback
A rule can be syntactically valid yet semantically wrong. Store the expected resolved mapping as a regression fixture, not merely the template JSON. This catches accidental reordering during refactors.
If a field has already been created with the wrong type, fixing the dynamic template does not rewrite the existing field. The corrected rule applies when a new field/index is created. An incompatible existing mapping still needs a new index and reindex/cutover.
4. Path governance beats global merchant keys
Allowing merchant_123_color,
merchant_124_color, and thousands of peer fields
creates global mapping growth. Prefer a stable extension object
path and a bounded vocabulary where search semantics need
first-class fields. If arbitrary key/value storage is required,
consider a flattened-like representation supported by the target
product and accept its query/typing limits rather than
pretending every arbitrary key deserves a dedicated mapped
field.
| Requirement | Preferred representation | Reason |
|---|---|---|
| Facet/filter on a known attribute | Explicit keyword/numeric/date field | Strong type, doc values and predictable query semantics. |
| Small family of extension fields | Dynamic template under bounded path | Flexible but governed. |
| Thousands of arbitrary metadata keys | Flattened-like/key-value strategy where supported | Avoid one mapping field per key; accept reduced typing semantics. |
| Security/tenant identity | Explicit field only | Never allow arbitrary dynamic mutation of authorization boundaries. |
5. Product-specific policy branch
# OpenSearch 3.8-specific governance option:
"dynamic": "strict_allow_templates"
# Meaning: an unknown field must match an approved dynamic template
# or the document is rejected.
# Do NOT copy this value into Elasticsearch 9.5.3.
For a cross-product course baseline, keep the mandatory template syntax portable and enforce the same policy through application validation and explicit mappings. If you choose OpenSearch-specific allow-template modes, version the deployment artifact by product.
6. Deterministic template tests
case: merchant boolean flag
input: merchant.flags.fragile = true
expect: type boolean
case: merchant code
input: merchant.codes.warehouse = "THR-07"
expect: type keyword, not analyzed text
case: leaf name suffix
input: campaign_label = "autumn"
expect: type keyword
case: ordinary prose
input: description = "Wireless headset"
expect: text + keyword multi-field
case: incompatible later value
input: merchant.flags.fragile = "sometimes"
expect: rejection or producer-contract failure; never silent remapping
Check your understanding
- Why place specific path rules before the generic string rule?
- What does fixing a template do to an already-created wrong field?
- Why keep tenant/security fields out of a generic extension namespace?
- What should a dynamic-template test assert besides indexing success?
- Which OpenSearch dynamic governance mode is not portable to Elasticsearch?
Review the answers
1. Dynamic templates are ordered; an earlier broad match can shadow the intended specific rule.
2. Nothing retroactive. Existing mappings remain; create a new index/reindex if the change is incompatible.
3. Authorization-critical semantics must be explicit, stable, reviewed and not controlled by arbitrary payload keys.
4. The resolved mapping/field capabilities and query/aggregation behavior expected from the chosen type.
5. The allow-templates dynamic modes such as strict_allow_templates/false_allow_templates.
Production judgment
Dynamic templates should reduce repetitive schema declarations without outsourcing schema ownership to incoming data. Version template order, review path patterns for accidental breadth, cap extension-field growth, and monitor the rate at which new mappings appear. If a rule changes search semantics, treat it as a schema migration even when the JSON diff looks small.
Summary and next step
You can now express controlled flexibility with ordered type/name/path rules. The next lesson turns those mappings and settings into reusable component templates and a composable index template whose final resolution is simulated before any index is created.
Authoritative references
- Elastic mapping overview — Dynamic versus explicit mapping and schema-management guidance.
- Elastic dynamic field mapping — Detection rules, dynamic modes, date detection and numeric detection.
- Elastic dynamic templates — match/path/type conditions, template variables, ordering and runtime-field options.
- Elastic templates — Composable index/component templates, precedence, priority and reusable configuration.
- Elastic simulate index template API — Dry-run composition and overlapping-template evidence.
- Elastic simulate index API — Resolve the configuration that a concrete index name would receive.
- Elastic update mapping examples — Why incompatible field-type changes require a new index and reindex.
- Elastic aliases — Index aliases, write-index behavior and no-downtime reindex patterns.
- OpenSearch mappings — Dynamic mapping rules and dynamic-template controls.
- OpenSearch dynamic parameter — OpenSearch-specific dynamic modes including allow-templates variants.
- OpenSearch index templates — Composable templates, priorities and component composition.
- OpenSearch component template API — Reusable settings/mappings/aliases and creation-time behavior.
- OpenSearch simulate index template API — Preview template resolution before index creation.
- OpenSearch reindex API — Source snapshot behavior and destination-index requirements.
- OpenSearch alias API — Alias creation/update APIs and the distinction from manage-alias actions.