Create or Update Index Mappings API
Introduced 1.0
Use this API to introduce new fields into an existing index or modify the search settings of existing fields. This operation lets you evolve your index schema without recreating the index from scratch.
You cannot use this operation to change the mapping or field type of a field that already contains indexed data. Modifying an existing field’s type risks making previously indexed data incompatible with the new mapping. If you need to change the type of an existing field, create a new index with the desired mappings and then use the Reindex operation to copy documents from the original index. To avoid downtime during reindexing, you can use aliases. For more information, see Changing the type of an existing field.
Endpoints
POST /{index}/_mapping
PUT /{index}/_mapping
Path parameters
The following table lists the available path parameters.
| Parameter | Required | Data type | Description |
|---|---|---|---|
index | Required | String | The name of the index to update. You can specify a single index name, a comma-separated list of index names, or a wildcard expression. To update the mapping of all indexes, use _all or *. |
Query parameters
The following table lists the available query parameters. All query parameters are optional.
| Parameter | Data type | Description | Default |
|---|---|---|---|
allow_no_indices | Boolean | Specifies whether to ignore wildcards that do not match any indexes. If false, the request returns an error when wildcards do not match any indexes. | true |
cluster_manager_timeout | String | The amount of time to wait for a connection to the cluster manager node. | 30s |
expand_wildcards | String | Specifies the types of indexes to which wildcard expressions can expand. Supports comma-separated values. Valid values are: - all: Match all indexes, including hidden indexes. - open: Match open indexes. - closed: Match closed indexes. - hidden: Match hidden indexes. Must be combined with open, closed, or both. - none: Do not accept wildcard expressions. | open |
ignore_unavailable | Boolean | Specifies whether to ignore indexes that are missing or closed. If true, missing or closed indexes are not included in the response. | false |
timeout | String | The amount of time to wait for a response. If no response is received before the timeout expires, the request fails and returns an error. | 30s |
write_index_only | Boolean | If true, the mappings are applied only to the current write index for the target. | false |
Request body fields
The following table lists the available request body fields.
| Field | Data type | Description |
|---|---|---|
properties | Object | Required. Defines the fields and their types for the index mapping. Each field can include a name, field data type, and mapping parameters. |
dynamic | String | Controls whether new fields are added dynamically. Valid values are true (new fields are added automatically), false (new fields are ignored), and strict (requests that contain unmapped fields are rejected). Default is true. |
Example: Adding fields to an index
The Create or Update Mappings API requires an existing index. The following example adds description and price fields to the products index:
PUT /products/_mapping
{
"properties": {
"description": {
"type": "text"
},
"price": {
"type": "float"
}
}
}response = client.indices.put_mapping(
index = "products",
body = {
"properties": {
"description": {
"type": "text"
},
"price": {
"type": "float"
}
}
}
)You can verify the mapping was applied by using the Get Mappings API:
GET /products/_mapping
Example: Updating multiple indexes
You can apply a mapping update to multiple indexes in a single request by specifying a comma-separated list of index names. The following example adds currency and tax_rate fields to both a US and EU regional catalog:
PUT /products-us,products-eu/_mapping
{
"properties": {
"currency": {
"type": "keyword"
},
"tax_rate": {
"type": "float"
}
}
}response = client.indices.put_mapping(
index = "products-us,products-eu",
body = {
"properties": {
"currency": {
"type": "keyword"
},
"tax_rate": {
"type": "float"
}
}
}
)Example: Adding properties to an existing object field
You can add new inner fields to an existing object field. Suppose the products index already has a manufacturer object with a name field. The following example adds a country keyword field to the manufacturer object:
PUT /products/_mapping
{
"properties": {
"manufacturer": {
"properties": {
"country": {
"type": "keyword"
}
}
}
}
}response = client.indices.put_mapping(
index = "products",
body = {
"properties": {
"manufacturer": {
"properties": {
"country": {
"type": "keyword"
}
}
}
}
}
)You can confirm the nested structure by retrieving the mapping:
GET /products/_mapping
Response
{
"products" : {
"mappings" : {
"properties" : {
"description" : {
"type" : "text"
},
"manufacturer" : {
"properties" : {
"country" : {
"type" : "keyword"
},
"name" : {
"type" : "text"
}
}
},
"price" : {
"type" : "float"
},
"product_name" : {
"type" : "text"
}
}
}
}
}
Example: Adding multi-fields to an existing field
Multi-fields allow you to index the same field in different ways. For instance, a text field used for full-text search can also have a keyword sub-field for sorting or aggregations. The following example adds a product_name.keyword sub-field with ignore_above set to 256, enabling exact-match filtering and sorting on product names:
PUT /products/_mapping
{
"properties": {
"product_name": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
}
}
}response = client.indices.put_mapping(
index = "products",
body = {
"properties": {
"product_name": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
}
}
}
)You can verify the multi-field configuration:
GET /products/_mapping
Response
{
"products" : {
"mappings" : {
"properties" : {
"description" : {
"type" : "text"
},
"manufacturer" : {
"properties" : {
"country" : {
"type" : "keyword"
},
"name" : {
"type" : "text"
}
}
},
"price" : {
"type" : "float"
},
"product_name" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
}
}
}
}
}
Example: Changing supported mapping parameters
Some mapping parameters can be updated for an existing field using the Create or Update Mappings API. For example, you can change the ignore_above value for a keyword field. The following example increases ignore_above from 20 to 50 for the sku field, allowing longer product codes to be indexed:
PUT /products/_mapping
{
"properties": {
"sku": {
"type": "keyword",
"ignore_above": 50
}
}
}response = client.indices.put_mapping(
index = "products",
body = {
"properties": {
"sku": {
"type": "keyword",
"ignore_above": 50
}
}
}
)You can confirm the updated parameter value:
GET /products/_mapping
Response
{
"products" : {
"mappings" : {
"properties" : {
"description" : {
"type" : "text"
},
"manufacturer" : {
"properties" : {
"country" : {
"type" : "keyword"
},
"name" : {
"type" : "text"
}
}
},
"price" : {
"type" : "float"
},
"product_name" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"sku" : {
"type" : "keyword",
"ignore_above" : 50
}
}
}
}
}
Example: Renaming a field using an alias
Because renaming a field makes previously stored data inaccessible under the new name, use an alias field type to provide an alternate way to reference the field. The following example creates an item_id alias that points to the existing product_id field, allowing queries to use either name:
PUT /products/_mapping
{
"properties": {
"item_id": {
"type": "alias",
"path": "product_id"
}
}
}response = client.indices.put_mapping(
index = "products",
body = {
"properties": {
"item_id": {
"type": "alias",
"path": "product_id"
}
}
}
)You can verify the alias was created:
GET /products/_mapping
Response
{
"products" : {
"mappings" : {
"properties" : {
"description" : {
"type" : "text"
},
"item_id" : {
"type" : "alias",
"path" : "product_id"
},
"manufacturer" : {
"properties" : {
"country" : {
"type" : "keyword"
},
"name" : {
"type" : "text"
}
}
},
"price" : {
"type" : "float"
},
"product_id" : {
"type" : "keyword"
},
"product_name" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"sku" : {
"type" : "keyword",
"ignore_above" : 50
}
}
}
}
}
Example: Changing the type of an existing field
You cannot directly change the field type of a field that already contains indexed data. Instead, create a new index with the correct mapping and use the Reindex API to copy documents from the original index.
The following example changes the weight field from integer to float so that fractional values (such as 0.75 kg) can be stored accurately.
First, create the new index with the updated field type:
PUT /products-v2
{
"mappings": {
"properties": {
"product_name": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"price": {
"type": "float"
},
"weight": {
"type": "float"
}
}
}
}response = client.indices.create(
index = "products-v2",
body = {
"mappings": {
"properties": {
"product_name": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"price": {
"type": "float"
},
"weight": {
"type": "float"
}
}
}
}
)Then reindex the data from the original index into the new one:
POST /_reindex
{
"source": {
"index": "products"
},
"dest": {
"index": "products-v2"
}
}response = client.reindex(
body = {
"source": {
"index": "products"
},
"dest": {
"index": "products-v2"
}
}
)Response
{
"took" : 8,
"timed_out" : false,
"total" : 2,
"updated" : 0,
"created" : 2,
"deleted" : 0,
"batches" : 1,
"version_conflicts" : 0,
"noops" : 0,
"retries" : {
"bulk" : 0,
"search" : 0
},
"throttled_millis" : 0,
"requests_per_second" : -1.0,
"throttled_until_millis" : 0,
"failures" : [ ]
}
Example response
A successful mapping update returns the following response:
{
"acknowledged": true
}
Response body fields
The following table lists all response body fields.
| Field | Data type | Description |
|---|---|---|
acknowledged | Boolean | Indicates whether the request was acknowledged by all relevant nodes in the cluster. |