Most Elasticsearch bugs and slow queries trace back to a field mapped as the wrong type.
A mapping is the schema of an index: each field's type and how it is indexed. If you don't define one, dynamic mapping guesses on first sight: numbers become long or float, ISO date strings date, and every other string becomes a text field with a .keyword subfield.
The crucial distinction is between the two string types:
- text is analyzed into terms for full-text search ("Blue Pen" becomes
blue,pen); you can't sort or aggregate on it efficiently, - keyword stores the exact value as one term, for filters, sorting, aggregations and ids ("SKU-001", "paid", email addresses).
Other common types: integer, long, float, scaled_float, double, date, boolean, ip, geo_point, object, nested, dense_vector. Multi-fields ("fields": { "raw": { "type": "keyword" } }) index one value both ways.
Define mappings explicitly for production indices: PUT /index { "mappings": { "properties": {...} } }. Set "dynamic": "strict" to reject unknown fields, or false to store but not index them; uncontrolled dynamic fields can lead to a mapping explosion (the default limit is 1,000 fields).
You can add new fields to an existing mapping, but you cannot change an existing field's type; that requires creating a new index and reindexing.
Example
PUT /orders
{
"mappings": {
"dynamic": "strict",
"properties": {
"order_id": { "type": "keyword" },
"status": { "type": "keyword" },
"customer": { "type": "text", "fields": { "raw": { "type": "keyword" } } },
"total": { "type": "scaled_float", "scaling_factor": 100 },
"placed_at": { "type": "date" },
"notes": { "type": "text" }
}
}
}
PUT /orders/_doc/1
{ "order_id": "A-1", "status": "paid", "customer": "Ana Petrosyan", "colour": "red" }
# 400 strict_dynamic_mapping_exception: [colour] not allowed
GET /orders/_mappingRemember
- text = analyzed for full-text; keyword = exact value for filters, sorts, aggs
- Dynamic mapping makes strings text + .keyword
- Define production mappings explicitly; consider dynamic: strict
- Existing field types can't change: reindex instead
Watch out for
- Mapping ids, statuses or emails as text and then wondering why exact filters and aggregations misbehave.