﻿---
title: Flattened field type
description: By default, each subfield in an object is mapped and indexed separately. If the names or types of the subfields are not known in advance, then they are...
url: https://www.elastic.co/elastic/docs-builder/docs/3028/reference/elasticsearch/mapping-reference/flattened
products:
  - Elasticsearch
applies_to:
  - Elastic Cloud Serverless: Generally available
  - Elastic Stack: Generally available
---

# Flattened field type
By default, each subfield in an object is mapped and indexed separately. If the names or types of the subfields are not known in advance, then they are [mapped dynamically](https://docs-v3-preview.elastic.dev/elastic/docs-builder/docs/3028/manage-data/data-store/mapping/dynamic-mapping).
The `flattened` type provides an alternative approach, where the entire object is mapped as a single field. Given an object, the `flattened` mapping will parse out its leaf values and index them into one field as keywords. The object’s contents can then be searched through simple queries and aggregations.
This data type can be useful for indexing objects with a large or unknown number of unique keys. Only one field mapping is created for the whole JSON object, which can help prevent a [mappings explosion](https://docs-v3-preview.elastic.dev/elastic/docs-builder/docs/3028/manage-data/data-store/mapping#mapping-limit-settings) from having too many distinct field mappings.
On the other hand, flattened object fields present a trade-off in terms of search functionality. Only basic queries are allowed, with no support for numeric range queries or highlighting. Further information on the limitations can be found in the [Supported operations](#supported-operations) section.
<note>
  The `flattened` mapping type should **not** be used for indexing all document content, as it treats all values as keywords and does not provide full search functionality. The default approach, where each subfield has its own entry in the mappings, works well in the majority of cases.
</note>

A flattened object field can be created as follows:
```json

{
  "mappings": {
    "properties": {
      "title": {
        "type": "text"
      },
      "labels": {
        "type": "flattened"
      }
    }
  }
}


{
  "title": "Results are not sorted correctly.",
  "labels": {
    "priority": "urgent",
    "release": ["v1.2.5", "v1.3.0"],
    "timestamp": {
      "created": 1541458026,
      "closed": 1541457010
    }
  }
}
```

During indexing, tokens are created for each leaf value in the JSON object. The values are indexed as string keywords, without analysis or special handling for numbers or dates.
Querying the top-level `flattened` field searches all leaf values in the object:
```json

{
  "query": {
    "term": {"labels": "urgent"}
  }
}
```

To query on a specific key in the flattened object, object dot notation is used:
```json

{
  "query": {
    "term": {"labels.release": "v1.3.0"}
  }
}
```


## Supported operations

Because of the similarities in the way values are indexed, `flattened` fields share much of the same mapping and search functionality as [`keyword`](https://www.elastic.co/elastic/docs-builder/docs/3028/reference/elasticsearch/mapping-reference/keyword) fields.
Currently, flattened object fields can be used with the following query types:
- `term`, `terms`, and `terms_set`
- `prefix`
- `range`
- `match` and `multi_match`
- `query_string` and `simple_query_string`
- `exists`

When querying, it is not possible to refer to field keys using wildcards, as in `{ "term": {"labels.time*": 1541457010}}`. Note that all queries, including `range`, treat the values as string keywords. Highlighting is not supported on `flattened` fields.
It is possible to sort on a flattened object field, as well as perform simple keyword-style aggregations such as `terms`. As with queries, there is no special support for numerics — all values in the JSON object are treated as keywords. When sorting, this implies that values are compared lexicographically.
Flattened object fields currently cannot be stored. It is not possible to specify the [`store`](https://www.elastic.co/elastic/docs-builder/docs/3028/reference/elasticsearch/mapping-reference/mapping-store) parameter in the mapping.

## Retrieving flattened fields

Field values and concrete subfields can be retrieved using the [fields parameter](/elastic/docs-builder/docs/3028/reference/elasticsearch/rest-apis/retrieve-selected-fields#search-fields-param). content. Since the `flattened` field maps an entire object with potentially many subfields as a single field, the response contains the unaltered structure from `_source`.
Single subfields, however, can be fetched by specifying them explicitly in the request. This only works for concrete paths, but not using wildcards:
```json

{
  "mappings": {
    "properties": {
      "flattened_field": {
        "type": "flattened"
      }
    }
  }
}


{
  "flattened_field" : {
    "subfield" : "value"
  }
}


{
  "fields": ["flattened_field.subfield"],
  "_source": false
}
```

```json
{
  "took": 2,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 1,
      "relation": "eq"
    },
    "max_score": 1.0,
    "hits": [{
      "_index": "my-index-000001",
      "_id": "1",
      "_score": 1.0,
      "fields": {
        "flattened_field.subfield" : [ "value" ]
      }
    }]
  }
}
```

You can also use a [Painless script](https://docs-v3-preview.elastic.dev/elastic/docs-builder/docs/3028/explore-analyze/scripting/modules-scripting-painless) to retrieve values from sub-fields of flattened fields. Instead of including `doc['<field_name>'].value` in your Painless script, use `doc['<field_name>.<sub-field_name>'].value`. For example, if you have a flattened field called `label` with a `release` sub-field, your Painless script would be `doc['labels.release'].value`.
For example, let’s say your mapping contains two fields, one of which is of the `flattened` type:
```json

{
  "mappings": {
    "properties": {
      "title": {
        "type": "text"
      },
      "labels": {
        "type": "flattened"
      }
    }
  }
}
```

Index a few documents containing your mapped fields. The `labels` field has three sub-fields:
```json

{"index":{}}
{"title":"Something really urgent","labels":{"priority":"urgent","release":["v1.2.5","v1.3.0"],"timestamp":{"created":1541458026,"closed":1541457010}}}
{"index":{}}
{"title":"Somewhat less urgent","labels":{"priority":"high","release":["v1.3.0"],"timestamp":{"created":1541458026,"closed":1541457010}}}
{"index":{}}
{"title":"Not urgent","labels":{"priority":"low","release":["v1.2.0"],"timestamp":{"created":1541458026,"closed":1541457010}}}
```

Because `labels` is a `flattened` field type, the entire object is mapped as a single field. To retrieve values from this sub-field in a Painless script, use the `doc['<field_name>.<sub-field_name>'].value` format.
```java
"script": {
  "source": """
    if (doc['labels.release'].value.equals('v1.3.0'))
    {emit(doc['labels.release'].value)}
    else{emit('Version mismatch')}
  """
```


## Mapped sub-fields

<applies-to>
  - Elastic Cloud Serverless: Generally available
  - Elastic Stack: Planned
</applies-to>

By default, all keys in a flattened field are indexed as untyped keyword values. The `properties` parameter allows specific keys to be mapped as their own typed fields, such as `keyword`, `ip`, `long`, `date`, or any other leaf field type. Mapped keys are indexed exclusively through their sub-field and are excluded from the flattened field's representation.
This is useful when certain keys within the flattened object need functionality that plain flattened indexing does not support, such as index sorting, field aliases, or typed queries (for example, IP range queries on an `ip` field).
```json

{
  "mappings": {
    "properties": {
      "attributes": {
        "type": "flattened",
        "properties": {
          "host.name": { "type": "keyword" },
          "host.ip": { "type": "ip" }
        }
      }
    }
  }
}


{
  "attributes": {
    "host.name": "web-1",
    "host.ip": "192.168.1.10",
    "region": "us-east-1"
  }
}
```

In this example, `attributes.host.name` is a keyword field and `attributes.host.ip` is an IP field, both with their full typed capabilities. The key `region` is not mapped, so it is indexed through the normal flattened mechanism. Searching on `attributes.host.ip` uses IP-aware queries:
```json

{
  "query": {
    "term": { "attributes.host.ip": "192.168.1.10" }
  }
}
```

Only leaf field types are allowed as sub-field types.
Object, nested, and flattened types cannot be used as properties of a flattened field.
Sub-fields may not use `copy_to` or `fields` (multi-fields) parameters.

## Passthrough sub-fields

<applies-to>
  - Elastic Cloud Serverless: Generally available
  - Elastic Stack: Planned
</applies-to>

The `passthrough` parameter makes the typed sub-fields defined in `properties` queryable at the root level of the index, without prefixing them with the flattened field name. This behaves similarly to [pass-through object fields](https://www.elastic.co/elastic/docs-builder/docs/3028/reference/elasticsearch/mapping-reference/passthrough).
```json

{
  "mappings": {
    "properties": {
      "labels": {
        "type": "flattened",
        "passthrough": { "priority": 10 },
        "properties": {
          "status": { "type": "keyword" },
          "count":  { "type": "long" }
        }
      }
    }
  }
}
```

With this mapping, `status` and `count` can be queried directly at the root level in addition to the standard prefixed path:
```json

{
  "query": {
    "term": { "status": "active" }
  }
}
```

The `priority` field inside the `passthrough` object is used to resolve conflicts when multiple passthrough sources (flattened fields or pass-through objects) expose sub-fields with the same leaf name. The source with the higher priority wins. Root-level concrete fields always take precedence over any passthrough alias, regardless of priority.

## Parameters for flattened object fields

The following mapping parameters are accepted:
<definitions>
  <definition term="depth_limit">
    The maximum allowed depth of the flattened object field, in terms of nested inner objects. If a flattened object field exceeds this limit, then an error will be thrown. Defaults to `20`. Note that `depth_limit` can be updated dynamically through the [update mapping](https://www.elastic.co/docs/api/doc/elasticsearch/operation/operation-indices-put-mapping) API.
  </definition>
  <definition term="doc_values">
    Should the field be stored on disk in a column-stride fashion, so that it can later be used for sorting, aggregations, or scripting? Accepts `true` (default) or `false`.
  </definition>
  <definition term="eager_global_ordinals">
    Should global ordinals be loaded eagerly on refresh? Accepts `true` or `false` (default). Enabling this is a good idea on fields that are frequently used for terms aggregations.
  </definition>
  <definition term="ignore_above">
    Leaf values longer than this limit will not be indexed. By default, there is no limit and all values will be indexed. Note that this limit applies to the leaf values within the flattened object field, and not the length of the entire field.
  </definition>
  <definition term="index">
    Determines if the field should be searchable. Accepts `true` (default) or `false`.
  </definition>
  <definition term="index_options">
    What information should be stored in the index for scoring purposes. Defaults to `docs` but can also be set to `freqs` to take term frequency into account when computing scores.
  </definition>
  <definition term="null_value">
    A string value which is substituted for any explicit `null` values within the flattened object field. Defaults to `null`, which means null fields are treated as if they were missing.
  </definition>
  <definition term="passthrough">
    (Optional, object) When set, the typed sub-fields defined in `properties` become queryable at the root level without a prefix. Requires a `priority` field (non-negative integer) used to resolve conflicts when multiple passthrough sources expose a sub-field with the same name; the higher priority wins, and root-level concrete fields always take precedence. Omitting this parameter disables passthrough behavior. Refer to [Passthrough sub-fields](#flattened-passthrough).
  </definition>
  <definition term="properties">
    (Optional, object) A map of key names to field mappings. Allows specific keys within the flattened object to be mapped as typed sub-fields. Each entry maps a key (using dot notation for nested keys) to a leaf field type definition. See [Mapped sub-fields](#flattened-properties).
  </definition>
  <definition term="similarity">
    Which scoring algorithm or *similarity* should be used. Defaults to `BM25`.
  </definition>
  <definition term="split_queries_on_whitespace">
    Whether [full text queries](https://www.elastic.co/elastic/docs-builder/docs/3028/reference/query-languages/query-dsl/full-text-queries) should split the input on whitespace when building a query for this field. Accepts `true` or `false` (default).
  </definition>
  <definition term="time_series_dimensions">
    (Optional, array of strings) A list of fields inside the flattened object, where each field is a dimension of the time series. Each field is specified using the relative path from the root field and does not include the root field name.
  </definition>
</definitions>


## Synthetic `_source`

Flattened fields support [synthetic`_source`](/elastic/docs-builder/docs/3028/reference/elasticsearch/mapping-reference/mapping-source-field#synthetic-source) in their default configuration.
Synthetic source may sort `flattened` field values and remove duplicates. For example:

```json

{
  "settings": {
    "index": {
      "mapping": {
        "source": {
          "mode": "synthetic"
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "flattened": { "type": "flattened" }
    }
  }
}

{
  "flattened": {
    "field": [ "apple", "apple", "banana", "avocado", "10", "200", "AVOCADO", "Banana", "Tangerine" ]
  }
}
```

Will become:
```json
{
  "flattened": {
    "field": [ "10", "200", "AVOCADO", "Banana", "Tangerine", "apple", "avocado", "banana" ]
  }
}
```

Synthetic source always uses nested objects instead of array of objects. For example:

```json

{
  "settings": {
    "index": {
      "mapping": {
        "source": {
          "mode": "synthetic"
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "flattened": { "type": "flattened" }
    }
  }
}

{
  "flattened": {
      "field": [
        { "id": 1, "name": "foo" },
        { "id": 2, "name": "bar" },
        { "id": 3, "name": "baz" }
      ]
  }
}
```

Will become (note the nested objects instead of the "flattened" array):
```json
{
    "flattened": {
      "field": {
          "id": [ "1", "2", "3" ],
          "name": [ "bar", "baz", "foo" ]
      }
    }
}
```

Synthetic source always uses single-valued fields for one-element arrays. For example:

```json

{
  "settings": {
    "index": {
      "mapping": {
        "source": {
          "mode": "synthetic"
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "flattened": { "type": "flattened" }
    }
  }
}

{
  "flattened": {
    "field": [ "foo" ]
  }
}
```

Will become (note the nested objects instead of the "flattened" array):
```json
{
  "flattened": {
    "field": "foo"
  }
}
```

Flattened fields allow for a key to contain both an object and a scalar value.
For example, consider the following flattened field `flattened`:
```json
{
  "flattened": {
    "foo.bar": "10",
    "foo": {
      "bar": {
        "baz": "20"
      }
    }
  }
}
```

Because `"foo.bar": "10"` is implicitly equivalent to `"foo": { "bar": "10" }`,
`"bar"` has both a scalar value `"10"`, and an object value of `{ "baz": "20" }`.
With synthetic source, to produce a valid JSON output, objects with such fields will appear differently in `_source`.
For example, if the field is defined in an index configured with synthetic source, the value of `_source` would be:
```json
{
  "flattened": {
    "foo": {
      "bar": "10",
      "bar.baz": "20"
    }
  }
}
```