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:

ApproachHow it worksWhen to use
Dynamic MappingElasticsearch guesses the type from the first document you addQuick experiments, prototyping
Explicit MappingYou define field types before adding documentsProduction 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

TypeUse CaseExample Value
textFull-text search on sentences and paragraphs"Organic green tea"
keywordExact match, sorting, aggregations"electronics", "IN"
integerWhole numbers42
floatDecimal numbers19.99
dateDates and timestamps"2024-06-15"
booleanTrue/false flagstrue
objectNested JSON objects{ "city": "Delhi" }
nestedArrays of objects that need independent querying[{...}, {...}]
geo_pointLatitude 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

Leave a Comment