Data Modeling
What to know
Mappings decide how fields are indexed and queried. text is analyzed for full-text search; keyword is stored verbatim for exact matching, sorting and aggregations. Multi-fields (title as text plus title.raw as keyword) give you both. Beyond scalars you have object, nested (each array element indexed independently), join (parent/child inside one index), date with an explicit format, scaled_float, ip, geo_point, and runtime fields computed at query time. Dynamic mapping guesses types - strings become text with a keyword sub-field capped by ignore_above: 256, JSON integers become long, date-like strings are detected - and you override that guessing with dynamic: strict|false|runtime or dynamic_templates.
Traps
- You cannot change an existing field's type or analyzer in place. The only path is reindex into a new index, usually behind an alias.
- Arrays of objects are flattened, so a query can match when the two fields came from different array elements. Use
nestedto prevent false positives, and remember queries then need"nested": {"path": ...}. - Keyword values longer than
ignore_abovestay in_sourcebut are not indexed, so term queries silently miss them. fielddata: trueon atextfield makes aggregations work but is a memory hazard; add akeywordsub-field instead.- Disabling
_sourcebreaks reindex, update APIs and highlighting.
Rule of thumb
Model before you index: settle text-versus-keyword, nested-versus-object, and date formats up front, because every later change costs a reindex plus an alias swap.