elasticsearch/docs/reference/mapping/params/copy-to.asciidoc
Liam Thompson 4034615e29
[DOCS] Clarify copy_to behavior with strict dynamic mappings (#111408)
* [DOCS] Clarify copy_to behavior with strict dynamic mappings

* Add id

* De-verbosify

* Delete pesky comma

* More info about root and nest

* Fixes per review, clarify non-recursive explanation

* Skip tests for illustrative example

* Fix example syntax

* Fix typo
2024-08-01 14:37:17 +02:00

167 lines
No EOL
4.4 KiB
Text

[[copy-to]]
=== `copy_to`
The `copy_to` parameter allows you to copy the values of multiple
fields into a group field, which can then be queried as a single
field.
TIP: If you often search multiple fields, you can improve search speeds by using
`copy_to` to search fewer fields. See <<search-as-few-fields-as-possible>>.
For example, the `first_name` and `last_name` fields can be copied to
the `full_name` field as follows:
[source,console]
--------------------------------------------------
PUT my-index-000001
{
"mappings": {
"properties": {
"first_name": {
"type": "text",
"copy_to": "full_name" <1>
},
"last_name": {
"type": "text",
"copy_to": "full_name" <1>
},
"full_name": {
"type": "text"
}
}
}
}
PUT my-index-000001/_doc/1
{
"first_name": "John",
"last_name": "Smith"
}
GET my-index-000001/_search
{
"query": {
"match": {
"full_name": { <2>
"query": "John Smith",
"operator": "and"
}
}
}
}
--------------------------------------------------
<1> The values of the `first_name` and `last_name` fields are copied to the
`full_name` field.
<2> The `first_name` and `last_name` fields can still be queried for the
first name and last name respectively, but the `full_name` field can be
queried for both first and last names.
Some important points:
* It is the field _value_ which is copied, not the terms (which result from the analysis process).
* The original <<mapping-source-field,`_source`>> field will not be modified to show the copied values.
* The same value can be copied to multiple fields, with `"copy_to": [ "field_1", "field_2" ]`
* You cannot copy recursively using intermediary fields.
The following configuration will not copy data from `field_1` to `field_3`:
+
[source,console]
----
PUT bad_example_index
{
"mappings": {
"properties": {
"field_1": {
"type": "text",
"copy_to": "field_2"
},
"field_2": {
"type": "text",
"copy_to": "field_3"
},
"field_3": {
"type": "text"
}
}
}
}
----
Instead, copy to multiple fields from the source field:
+
[source,console]
----
PUT good_example_index
{
"mappings": {
"properties": {
"field_1": {
"type": "text",
"copy_to": ["field_2", "field_3"]
},
"field_2": {
"type": "text"
},
"field_3": {
"type": "text"
}
}
}
}
----
NOTE: `copy_to` is not supported for field types where values take the form of objects, e.g. `date_range`.
[float]
[[copy-to-dynamic-mapping]]
==== Dynamic mapping
Consider the following points when using `copy_to` with dynamic mappings:
* If the target field does not exist in the index mappings, the usual
<<dynamic-mapping,dynamic mapping>> behavior applies. By default, with
<<dynamic,`dynamic`>> set to `true`, a non-existent target field will be
dynamically added to the index mappings.
* If `dynamic` is set to `false`, the
target field will not be added to the index mappings, and the value will not be
copied.
* If `dynamic` is set to `strict`, copying to a non-existent field will
result in an error.
+
** If the target field is nested, then `copy_to` fields must specify the full path to the nested field.
Omitting the full path will lead to a `strict_dynamic_mapping_exception`.
Use `"copy_to": ["parent_field.child_field"]` to correctly target a nested field.
+
For example:
+
[source,console]
--------------------------------------------------
PUT /test_index
{
"mappings": {
"dynamic": "strict",
"properties": {
"description": {
"properties": {
"notes": {
"type": "text",
"copy_to": [ "description.notes_raw"], <1>
"analyzer": "standard",
"search_analyzer": "standard"
},
"notes_raw": {
"type": "keyword"
}
}
}
}
}
}
--------------------------------------------------
<1> The `notes` field is copied to the `notes_raw` field. Targeting `notes_raw` alone instead of `description.notes_raw`
would lead to a `strict_dynamic_mapping_exception`.
+
In this example, `notes_raw` is not defined at the root of the mapping, but under the `description` field.
Without the fully qualified path, {es} would interpret the `copy_to` target as a root-level field, not as a nested field under `description`.