Skip to content
Merged
Show file tree
Hide file tree
Changes from 27 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
77277c2
Add object param for keeping synthetic source
kkrik-es Sep 27, 2024
468d250
Update docs/changelog/113690.yaml
kkrik-es Sep 27, 2024
efa3c77
Merge branch 'main' into synthetic-source/keep-object-param
kkrik-es Sep 27, 2024
3b30147
fix merging
kkrik-es Sep 28, 2024
d0d31b5
Merge remote-tracking branch 'origin/synthetic-source/keep-object-par…
kkrik-es Sep 28, 2024
3ee3a86
Merge branch 'main' into synthetic-source/keep-object-param
kkrik-es Sep 29, 2024
16c9865
add tests
kkrik-es Sep 29, 2024
4000ac1
Merge branch 'main' into synthetic-source/keep-object-param
kkrik-es Sep 30, 2024
51a5f71
merge
kkrik-es Sep 30, 2024
6dcdf44
fix randomized tests
kkrik-es Sep 30, 2024
9d8232c
Merge branch 'refs/heads/main' into synthetic-source/keep-object-param
kkrik-es Oct 1, 2024
b8b85c7
add documentation
kkrik-es Oct 1, 2024
ee047bc
dedup id in docs
kkrik-es Oct 2, 2024
aea0cc5
Merge branch 'main' into synthetic-source/keep-object-param
kkrik-es Oct 2, 2024
58fd5b9
Merge branch 'main' into synthetic-source/keep-object-param
kkrik-es Oct 3, 2024
c214eb4
update documentation
kkrik-es Oct 3, 2024
97b6c01
update documentation
kkrik-es Oct 3, 2024
f4ddb0e
fix bwc
kkrik-es Oct 3, 2024
18dc913
fix bwc
kkrik-es Oct 3, 2024
b5f1d71
fix unintended
kkrik-es Oct 3, 2024
432757f
Revert "fix bwc"
kkrik-es Oct 3, 2024
771bc38
Revert "fix bwc"
kkrik-es Oct 3, 2024
895e08f
add missing test
kkrik-es Oct 3, 2024
d3b5c30
fix transform
kkrik-es Oct 3, 2024
de651f8
fix transform
kkrik-es Oct 3, 2024
6887504
fix transform
kkrik-es Oct 3, 2024
92d5c1b
fix transform
kkrik-es Oct 3, 2024
c4d0111
fix transform
kkrik-es Oct 3, 2024
f9d0330
Merge branch 'elastic:main' into synthetic-source/keep-object-param
kkrik-es Oct 3, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions docs/changelog/113690.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
pr: 113690
summary: Add object param for keeping synthetic source
area: Mapping
type: enhancement
issues: []
144 changes: 134 additions & 10 deletions docs/reference/mapping/fields/synthetic-source.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -32,18 +32,25 @@ space. Additional latency can be avoided by not loading `_source` field in queri

[[synthetic-source-fields]]
===== Supported fields
Synthetic `_source` is supported by all field types. Depending on implementation details, field types have different properties when used with synthetic `_source`.
Synthetic `_source` is supported by all field types. Depending on implementation details, field types have different
properties when used with synthetic `_source`.

<<synthetic-source-fields-native-list, Most field types>> construct synthetic `_source` using existing data, most commonly <<doc-values,`doc_values`>> and <<stored-fields, stored fields>>. For these field types, no additional space is needed to store the contents of `_source` field. Due to the storage layout of <<doc-values,`doc_values`>>, the generated `_source` field undergoes <<synthetic-source-modifications, modifications>> compared to original document.
<<synthetic-source-fields-native-list, Most field types>> construct synthetic `_source` using existing data, most
commonly <<doc-values,`doc_values`>> and <<stored-fields, stored fields>>. For these field types, no additional space
is needed to store the contents of `_source` field. Due to the storage layout of <<doc-values,`doc_values`>>, the
generated `_source` field undergoes <<synthetic-source-modifications, modifications>> compared to original document.

For all other field types, the original value of the field is stored as is, in the same way as the `_source` field in non-synthetic mode. In this case there are no modifications and field data in `_source` is the same as in the original document. Similarly, malformed values of fields that use <<ignore-malformed,`ignore_malformed`>> or <<ignore-above,`ignore_above`>> need to be stored as is. This approach is less storage efficient since data needed for `_source` reconstruction is stored in addition to other data required to index the field (like `doc_values`).
For all other field types, the original value of the field is stored as is, in the same way as the `_source` field in
non-synthetic mode. In this case there are no modifications and field data in `_source` is the same as in the original
document. Similarly, malformed values of fields that use <<ignore-malformed,`ignore_malformed`>> or
<<ignore-above,`ignore_above`>> need to be stored as is. This approach is less storage efficient since data needed for
`_source` reconstruction is stored in addition to other data required to index the field (like `doc_values`).

[[synthetic-source-restrictions]]
===== Synthetic `_source` restrictions

Synthetic `_source` cannot be used together with field mappings that use <<copy-to,`copy_to`>>.

Some field types have additional restrictions. These restrictions are documented in the **synthetic `_source`** section of the field type's <<mapping-types,documentation>>.
Some field types have additional restrictions. These restrictions are documented in the **synthetic `_source`** section
of the field type's <<mapping-types,documentation>>.

[[synthetic-source-modifications]]
===== Synthetic `_source` modifications
Expand Down Expand Up @@ -144,6 +151,42 @@ Will become:
----
// TEST[s/^/{"_source":/ s/\n$/}/]

This impacts how source contents can be referenced in <<modules-scripting-using,scripts>>. For instance, referencing
a script in its original source form will return null:

[source,js]
----
"script": { "source": """ emit(params._source['foo.bar.baz']) """ }
----
// NOTCONSOLE

Instead, source references need to be in line with the mapping structure:

[source,js]
----
"script": { "source": """ emit(params._source['foo']['bar']['baz']) """ }
----
// NOTCONSOLE

or simply

[source,js]
----
"script": { "source": """ emit(params._source.foo.bar.baz) """ }
----
// NOTCONSOLE

The following <<modules-scripting-fields, field APIs>> are preferable as, in addition to being agnostic to the
mapping structure, they make use of docvalues if available and fall back to synthetic source only when needed. This
reduces source synthesizing, a slow and costly operation.

[source,js]
----
"script": { "source": """ emit(field('foo.bar.baz').get(null)) """ }
"script": { "source": """ emit($('foo.bar.baz', null)) """ }
----
// NOTCONSOLE

[[synthetic-source-modifications-alphabetical]]
====== Alphabetical sorting
Synthetic `_source` fields are sorted alphabetically. The
Expand All @@ -155,18 +198,99 @@ that ordering.

[[synthetic-source-modifications-ranges]]
====== Representation of ranges
Range field values (e.g. `long_range`) are always represented as inclusive on both sides with bounds adjusted accordingly. See <<range-synthetic-source-inclusive, examples>>.
Range field values (e.g. `long_range`) are always represented as inclusive on both sides with bounds adjusted
accordingly. See <<range-synthetic-source-inclusive, examples>>.

[[synthetic-source-precision-loss-for-point-types]]
====== Reduced precision of `geo_point` values
Values of `geo_point` fields are represented in synthetic `_source` with reduced precision. See <<geo-point-synthetic-source, examples>>.
Values of `geo_point` fields are represented in synthetic `_source` with reduced precision. See
<<geo-point-synthetic-source, examples>>.

[[synthetic-source-keep]]
====== Minimizing source modifications

It is possible to avoid synthetic source modifications for a particular object or field, at extra storage cost.
This is controlled through param `synthetic_source_keep` with the following option:

- `none`: synthetic source diverges from the original source as described above (default).
- `arrays`: arrays of the corresponding field or object preserve the original element ordering and duplicate elements.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

The synthetic source fragment for such arrays is not guaranteed to match the original source exactly, e.g. array
`[1, 2, [5], [[4, [3]]], 5]` may appear as-is or in an equivalent format like `[1, 2, 5, 4, 3, 5]`. The exact format
may change in the future, in an effort to reduce the storage overhead of this option.
- `all`: the source for both singleton instances and arrays of the corresponding field or object gets recorded. When
applied to objects, the source of all sub-objects and sub-fields gets captured. Furthermore, the original source of
arrays gets captured and appears in synthetic source with no modifications.

For instance:

[source,console,id=create-index-with-synthetic-source-keep]
----
PUT idx_keep
{
"mappings": {
"_source": {
"mode": "synthetic"
},
"properties": {
"path": {
"type": "object",
"synthetic_source_keep": "all"
},
"ids": {
"type": "integer",
"synthetic_source_keep": "arrays"
}
}
}
}
----
// TEST

[source,console,id=synthetic-source-keep-example]
----
PUT idx_keep/_doc/1
{
"path": {
"to": [
{ "foo": [3, 2, 1] },
{ "foo": [30, 20, 10] }
],
"bar": "baz"
},
"ids": [ 200, 100, 300, 100 ]
}
----
// TEST[s/$/\nGET idx_keep\/_doc\/1?filter_path=_source\n/]

returns the original source, with no array deduplication and sorting:

[source,console-result]
----
{
"path": {
"to": [
{ "foo": [3, 2, 1] },
{ "foo": [30, 20, 10] }
],
"bar": "baz"
},
"ids": [ 200, 100, 300, 100 ]
}
----
// TEST[s/^/{"_source":/ s/\n$/}/]

The option for capturing the source of arrays can be applied at index level, by setting
`index.mapping.synthetic_source_keep` to `arrays`. This applies to all objects and fields in the index, except for
the ones with explicit overrides of `synthetic_source_keep` set to `none`. In this case, the storage overhead grows
with the number and sizes of arrays present in source of each document, naturally.

[[synthetic-source-fields-native-list]]
===== Field types that support synthetic source with no storage overhead
The following field types support synthetic source using data from <<doc-values,`doc_values`>> or <<stored-fields, stored fields>>, and require no additional storage space to construct the `_source` field.
The following field types support synthetic source using data from <<doc-values,`doc_values`>> or
<stored-fields, stored fields>>, and require no additional storage space to construct the `_source` field.

NOTE: If you enable the <<ignore-malformed,`ignore_malformed`>> or <<ignore-above,`ignore_above`>> settings, then additional storage is required to store ignored field values for these types.
NOTE: If you enable the <<ignore-malformed,`ignore_malformed`>> or <<ignore-above,`ignore_above`>> settings, then
additional storage is required to store ignored field values for these types.

** <<aggregate-metric-double-synthetic-source, `aggregate_metric_double`>>
** {plugins}/mapper-annotated-text-usage.html#annotated-text-synthetic-source[`annotated-text`]
Expand Down
2 changes: 1 addition & 1 deletion rest-api-spec/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -57,5 +57,5 @@ tasks.named("precommit").configure {
tasks.named("yamlRestCompatTestTransform").configure({task ->
task.skipTest("indices.sort/10_basic/Index Sort", "warning does not exist for compatibility")
task.skipTest("search/330_fetch_fields/Test search rewrite", "warning does not exist for compatibility")
task.skipTestsByFilePattern("indices.create/synthetic_source*.yml", "@UpdateForV9 -> tests do not pass after bumping API version to 9 [ES-9597]")
task.skipTestsByFilePattern("*create/*synthetic_source*.yml", "@UpdateForV9 -> tests do not pass after bumping API version to 9 [ES-9597]")
})
Original file line number Diff line number Diff line change
Expand Up @@ -895,7 +895,7 @@ doubly nested object:
---
subobjects auto:
- requires:
cluster_features: ["mapper.subobjects_auto"]
cluster_features: ["mapper.subobjects_auto", "mapper.bwc_workaround_9_0"]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would adding gte_v8.16.0 as cluster feature avoid adding the new mapper.bwc_workaround_9_0 cluster feature?

Copy link
Contributor Author

@kkrik-es kkrik-es Oct 3, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If added in skip, it will disable the test in main. If added here, it won't fix the test failures.

reason: requires tracking ignored source and supporting subobjects auto setting

- do:
Expand All @@ -920,7 +920,7 @@ subobjects auto:
id:
type: keyword
stored:
store_array_source: true
synthetic_source_keep: arrays
properties:
span:
properties:
Expand Down
Loading