Elasticsearch Mappings and Data Types
A mapping defines the shape of your documents — what fields exist and what type of data each field holds. Getting mappings right prevents common search problems before they happen.
The Blueprint Analogy
Building Blueprint = Mapping Room type = Field data type Room dimensions = Field options (analyzer, format, etc.) Actual building = Index with stored documents
Just as you cannot change a room's purpose after construction without major work, changing a field's data type after documents exist in an index requires creating a new index.
Dynamic Mapping vs Explicit Mapping
Elasticsearch supports two approaches:
| Approach | How it works | When to use |
|---|---|---|
| Dynamic Mapping | Elasticsearch guesses the type from the first document you add | Quick experiments, prototyping |
| Explicit Mapping | You define field types before adding documents | Production systems, precise control |
Dynamic mapping makes assumptions that sometimes cause bugs. For example, it stores a field like "01" as a string one day, then you add a document with "01.5" and it now expects a number — conflict. Explicit mapping avoids this.
Common Data Types
| Type | Use Case | Example Value |
|---|---|---|
| text | Full-text search on sentences and paragraphs | "Organic green tea" |
| keyword | Exact match, sorting, aggregations | "electronics", "IN" |
| integer | Whole numbers | 42 |
| float | Decimal numbers | 19.99 |
| date | Dates and timestamps | "2024-06-15" |
| boolean | True/false flags | true |
| object | Nested JSON objects | { "city": "Delhi" } |
| nested | Arrays of objects that need independent querying | [{...}, {...}] |
| geo_point | Latitude and longitude coordinates | { "lat": 28.6, "lon": 77.2 } |
text vs keyword — The Most Important Distinction
text field:
"Organic Green Tea"
|
v
Analyzed into tokens: ["organic", "green", "tea"]
Used for: full-text search ("find products with green")
keyword field:
"Organic Green Tea"
|
v
Stored as-is: "Organic Green Tea"
Used for: exact match, sorting, grouping
Many fields need both. Elasticsearch supports a multi-field setup where one field has both a text and keyword version:
"name": {
"type": "text",
"fields": {
"raw": {
"type": "keyword"
}
}
}
Now name supports full-text search and name.raw supports exact sorting.
Creating an Index with Explicit Mapping
PUT /products
{
"mappings": {
"properties": {
"name": { "type": "text" },
"category": { "type": "keyword" },
"price": { "type": "float" },
"in_stock": { "type": "boolean" },
"created_at": { "type": "date", "format": "yyyy-MM-dd" }
}
}
}
Viewing the Mapping of an Index
GET /products/_mapping
Elasticsearch returns the full mapping definition so you can confirm every field's type.
Adding a New Field to an Existing Mapping
You can add new fields to a live index without downtime:
PUT /products/_mapping
{
"properties": {
"rating": { "type": "float" }
}
}
What You Cannot Change
Once documents exist in an index, you cannot change an existing field's type. The fix is to create a new index with the correct mapping, then reindex (copy) documents into it using the Reindex API:
POST /_reindex
{
"source": { "index": "products" },
"dest": { "index": "products_v2" }
}
Mapping Gotchas to Avoid
- Do not store prices as text — use float or integer for range queries to work
- Do not use text for fields you plan to sort or aggregate — use keyword
- Always set a date format explicitly to avoid parsing errors across different systems
- Use nested type instead of object when you store arrays of objects and need to query individual items inside each array element independently
