The flattened field type indexes an entire JSON object as a single keyword-style field. Every leaf value inside the object is stored as a keyword under one mapping entry, regardless of how many keys the object has or how deep it nests. Use flattened when you have JSON sub-trees with unbounded or unknown keys - tags from user input, third-party payloads, vendor-specific metadata - and you want to keep them searchable without adding hundreds of distinct mappings to the index.
How Flattened Fields Work
A flattened field maps to one Lucene field under the hood. When a document is indexed, Elasticsearch walks the object, concatenates each leaf path with its value, and indexes them all into the same inverted index. Querying metadata: foo searches across every leaf in the flattened tree; querying metadata.user.id: 42 searches only that path. Because every leaf is treated as a keyword, there is no analyzer chain - no tokenization, no stemming, no lowercase folding unless you add it via normalizer.
This design trades flexibility for predictability. You never blow past index.mapping.total_fields.limit, because a flattened sub-tree counts as a single field. But you also lose full-text search, numeric range queries on leaves, and most aggregations on inner paths. Sub-paths support only term, terms, prefix, range (lexicographic, since values are strings), exists, and match (over keyword-tokenized values).
PUT events
{
"mappings": {
"properties": {
"labels": { "type": "flattened" }
}
}
}
POST events/_doc
{
"labels": {
"env": "prod",
"region": "eu-west-1",
"tags": ["search", "ingest"]
}
}
GET events/_search
{
"query": { "term": { "labels.env": "prod" } }
}
Flattened Field Configuration
| Parameter | Default | Notes |
|---|---|---|
depth_limit |
20 | Maximum nesting depth inside the flattened object. Exceeding throws a mapping exception. |
ignore_above |
2147483647 | Skip indexing any leaf value longer than N characters. |
null_value |
none | Substitute for null leaves at index time. |
similarity |
BM25 | Scoring function for the flattened keyword index. |
split_queries_on_whitespace |
false | If true, full-text queries are split on whitespace before lookup. |
index_options |
docs |
What to store in the inverted index (docs, freqs, positions, offsets). |
There is no analyzer parameter - flattened values are not analyzed. There is no per-leaf type either; numeric values become strings and sort/range comparisons are lexicographic. The 1000-leaves-per-field default that earlier guidance mentioned is actually the field-count cap on the index, not a flattened-specific cap; flattened sub-trees are exempt from it by design.
Common Pitfalls with Flattened Fields
- Expecting full-text search on inner paths. There is no analyzer;
matchqueries againstflattened.bodybehave like a keywordmatch, not a tokenized one. - Range queries on numeric-looking leaves.
range: { "labels.count": { "gte": 10 } }compares"10"to"9"as strings;"9" > "10"lexicographically. - Aggregations on inner paths.
termsaggregations against subfields of a flattened field work but are limited; sub-aggregations and metric aggregations on inner numeric paths don't work because there is no per-leaf numeric type. - Sorting on flattened subfields. Sorting works lexicographically only.
- Using flattened when
nestedis the right answer. If you need correlated matches inside arrays of objects (first_name AND last_name from the same entry), flattened cannot do that - use `nested`. - Assuming
_terms_enumworks. The Terms Enum API does not support flattened fields.
Operating Indices with Flattened Fields
Flattened is often the right call for log and telemetry ingestion where the producer keeps adding fields. It is the only built-in way to keep dynamic JSON payloads queryable without periodically retuning index.mapping.total_fields.limit or hitting mapping explosion. Pulse tracks mapping growth across ingest indices and flags candidates that should be migrated to flattened before a mapping-explosion incident, including the index templates and component templates that need updating.
Frequently Asked Questions
Q: When should I use flattened instead of nested in Elasticsearch?
A: Use flattened for JSON sub-trees with arbitrary or unbounded keys where you only need keyword-level lookups. Use nested when the data is an array of objects whose inner fields need to be queried in correlated combinations (same array entry). Flattened is far cheaper but cannot preserve intra-object correlation.
Q: Can I run full-text or analyzed search on a flattened field?
A: No. Every leaf is indexed as a keyword. There is no analyzer, no stemming, no lowercasing unless you attach a normalizer. If you need analyzed search, model the field as text or use a multi-field with a separate text subfield.
Q: What is the maximum depth of a flattened object?
A: 20 levels by default, controlled by depth_limit. Anything deeper fails at index time with a mapping exception. Raising the limit is supported but encourages mappings that would be better redesigned.
Q: Do flattened fields count toward index.mapping.total_fields.limit?
A: Each flattened field counts as one field, regardless of how many leaves the indexed objects contain. That is the main reason to use flattened - it caps mapping growth at one entry per dynamic sub-tree.
Q: Can I aggregate or sort on inner paths of a flattened field?
A: terms aggregations on inner paths work. Metric aggregations on inner numeric leaves do not, because every value is a keyword. Sorting works lexicographically only. If you need numeric sort or stats, extract that field as a top-level numeric mapping at ingest.
Q: Does flattened support the Terms Enum API?
A: No. The _terms_enum endpoint does not support flattened fields. Use a terms aggregation with a prefix include filter as a substitute, accepting the cost difference.
Related Reading
- Elasticsearch nested field data type: when you need correlated inner-field queries instead.
- Elasticsearch index.mapping.total_fields.limit: the mapping-cap setting that flattened helps you stay under.
- Elasticsearch too many fields / mapping explosion: the failure mode flattened was designed to prevent.
- Elasticsearch create index with mapping: declaring flattened fields up front in your index template.
- Elasticsearch IllegalArgumentException: mapper conflicts: the error you get when you try to convert an existing object field to flattened on the same index.