Skip to content

Commit 61025ff

Browse files
Fix dropped ignore above fields (#137394)
Currently, the CompositeSyntheticFieldLoaders for the various text-family field mappers only load the stored fields containing the original non-ignored values if ignore_above is set to a non-default value. But if a value is ignored due to hitting a default ignore_above limit, it won't be loaded by the field loader. This PR corrects that logic. Fixes #137360. Co-authored-by: Felix Barnsteiner <[email protected]>
1 parent 0ab3240 commit 61025ff

File tree

9 files changed

+218
-8
lines changed

9 files changed

+218
-8
lines changed

docs/changelog/137394.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
pr: 137394
2+
summary: Fix dropped ignore above fields
3+
area: Mapping
4+
type: bug
5+
issues:
6+
- 137360

modules/mapper-extras/src/main/java/org/elasticsearch/index/mapper/extras/MatchOnlyTextFieldMapper.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,8 @@ private IOFunction<LeafReaderContext, CheckedIntFunction<List<Object>, IOExcepti
295295
String parentFieldName = searchExecutionContext.parentPath(name());
296296
var parent = searchExecutionContext.lookup().fieldType(parentFieldName);
297297

298-
if (parent instanceof KeywordFieldMapper.KeywordFieldType keywordParent && keywordParent.ignoreAbove().isSet()) {
298+
if (parent instanceof KeywordFieldMapper.KeywordFieldType keywordParent
299+
&& keywordParent.ignoreAbove().valuesPotentiallyIgnored()) {
299300
final String parentFallbackFieldName = keywordParent.syntheticSourceFallbackFieldName();
300301
if (parent.isStored()) {
301302
return storedFieldFetcher(parentFieldName, parentFallbackFieldName);
@@ -323,7 +324,7 @@ private IOFunction<LeafReaderContext, CheckedIntFunction<List<Object>, IOExcepti
323324
final SearchExecutionContext searchExecutionContext,
324325
final KeywordFieldMapper.KeywordFieldType keywordDelegate
325326
) {
326-
if (keywordDelegate.ignoreAbove().isSet()) {
327+
if (keywordDelegate.ignoreAbove().valuesPotentiallyIgnored()) {
327328
// because we don't know whether the delegate field will be ignored during parsing, we must also check the current field
328329
String fieldName = name();
329330
String fallbackName = syntheticSourceFallbackFieldName();

server/src/main/java/org/elasticsearch/index/mapper/KeywordFieldMapper.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1407,7 +1407,7 @@ protected BytesRef preserve(BytesRef value) {
14071407

14081408
// if ignore_above is set, then there is a chance that this field will be ignored. In such cases, we save an
14091409
// extra copy of the field for supporting synthetic source. This layer will check that copy.
1410-
if (fieldType().ignoreAbove.isSet()) {
1410+
if (fieldType().ignoreAbove.valuesPotentiallyIgnored()) {
14111411
final String fieldName = fieldType().syntheticSourceFallbackFieldName();
14121412
layers.add(new CompositeSyntheticFieldLoader.StoredFieldLayer(fieldName) {
14131413
@Override

server/src/main/java/org/elasticsearch/index/mapper/Mapper.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ default boolean supportsVersion(IndexVersion indexCreatedVersion) {
136136
* This class models the ignore_above parameter in indices.
137137
*/
138138
public static final class IgnoreAbove {
139-
139+
// We use Integer.MAX_VALUE to represent a no-op, accepting all values.
140140
public static final int IGNORE_ABOVE_DEFAULT_VALUE = Integer.MAX_VALUE;
141141
public static final int IGNORE_ABOVE_DEFAULT_VALUE_FOR_LOGSDB_INDICES = 8191;
142142

@@ -172,6 +172,15 @@ public boolean isSet() {
172172
return Integer.valueOf(get()).equals(defaultValue) == false;
173173
}
174174

175+
/**
176+
* Returns whether values are potentially ignored, either by an explicitly configured ignore_above or by the default value.
177+
*/
178+
public boolean valuesPotentiallyIgnored() {
179+
// We use Integer.MAX_VALUE to represent accepting all values. If the value is anything else, then either we have an
180+
// explicitly configured ignore_above, or we have a non no-op default.
181+
return get() != Integer.MAX_VALUE;
182+
}
183+
175184
/**
176185
* Returns whether the given string will be ignored.
177186
*/

server/src/main/java/org/elasticsearch/index/mapper/TextFieldMapper.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1026,15 +1026,15 @@ public boolean isAggregatable() {
10261026
* A delegate by definition must have doc_values or be stored so most of the time it can be used for loading.
10271027
*/
10281028
public boolean canUseSyntheticSourceDelegateForLoading() {
1029-
return syntheticSourceDelegate.isPresent() && syntheticSourceDelegate.get().ignoreAbove().isSet() == false;
1029+
return syntheticSourceDelegate.isPresent() && syntheticSourceDelegate.get().ignoreAbove().valuesPotentiallyIgnored() == false;
10301030
}
10311031

10321032
/**
10331033
* Returns true if the delegate sub-field can be used for querying only (ie. isSearchable must be true)
10341034
*/
10351035
public boolean canUseSyntheticSourceDelegateForQuerying() {
10361036
return syntheticSourceDelegate.isPresent()
1037-
&& syntheticSourceDelegate.get().ignoreAbove().isSet() == false
1037+
&& syntheticSourceDelegate.get().ignoreAbove().valuesPotentiallyIgnored() == false
10381038
&& syntheticSourceDelegate.get().isSearchable();
10391039
}
10401040

server/src/main/java/org/elasticsearch/index/mapper/flattened/FlattenedFieldMapper.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -926,7 +926,7 @@ protected SyntheticSourceSupport syntheticSourceSupport() {
926926
() -> new FlattenedSortedSetDocValuesSyntheticFieldLoader(
927927
fullPath(),
928928
fullPath() + KEYED_FIELD_SUFFIX,
929-
fieldType().ignoreAbove.isSet() ? fullPath() + KEYED_IGNORED_VALUES_FIELD_SUFFIX : null,
929+
fieldType().ignoreAbove.valuesPotentiallyIgnored() ? fullPath() + KEYED_IGNORED_VALUES_FIELD_SUFFIX : null,
930930
leafName()
931931
)
932932
);

server/src/test/java/org/elasticsearch/index/IgnoreAboveTests.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ public void test_ignore_above_with_value_and_index_mode_and_index_version() {
2525
// when/then
2626
assertEquals(123, ignoreAbove.get());
2727
assertTrue(ignoreAbove.isSet());
28+
assertTrue(ignoreAbove.valuesPotentiallyIgnored());
2829
}
2930

3031
public void test_ignore_above_with_value_only() {
@@ -34,6 +35,7 @@ public void test_ignore_above_with_value_only() {
3435
// when/then
3536
assertEquals(123, ignoreAbove.get());
3637
assertTrue(ignoreAbove.isSet());
38+
assertTrue(ignoreAbove.valuesPotentiallyIgnored());
3739
}
3840

3941
public void test_ignore_above_with_null_value_should_throw() {
@@ -52,6 +54,7 @@ public void test_ignore_above_with_null_value() {
5254
// when/then
5355
assertEquals(Mapper.IgnoreAbove.IGNORE_ABOVE_DEFAULT_VALUE, ignoreAbove.get());
5456
assertFalse(ignoreAbove.isSet());
57+
assertFalse(ignoreAbove.valuesPotentiallyIgnored());
5558
}
5659

5760
public void test_ignore_above_with_null_value_and_logsdb_index_mode() {
@@ -61,6 +64,7 @@ public void test_ignore_above_with_null_value_and_logsdb_index_mode() {
6164
// when/then
6265
assertEquals(Mapper.IgnoreAbove.IGNORE_ABOVE_DEFAULT_VALUE_FOR_LOGSDB_INDICES, ignoreAbove.get());
6366
assertFalse(ignoreAbove.isSet());
67+
assertTrue(ignoreAbove.valuesPotentiallyIgnored());
6468
}
6569

6670
public void test_ignore_above_with_null_everything() {
@@ -70,6 +74,7 @@ public void test_ignore_above_with_null_everything() {
7074
// when/then
7175
assertEquals(Mapper.IgnoreAbove.IGNORE_ABOVE_DEFAULT_VALUE, ignoreAbove.get());
7276
assertFalse(ignoreAbove.isSet());
77+
assertFalse(ignoreAbove.valuesPotentiallyIgnored());
7378
}
7479

7580
public void test_ignore_above_default_for_standard_indices() {
@@ -79,6 +84,7 @@ public void test_ignore_above_default_for_standard_indices() {
7984
// when/then
8085
assertEquals(Mapper.IgnoreAbove.IGNORE_ABOVE_DEFAULT_VALUE, ignoreAbove.get());
8186
assertFalse(ignoreAbove.isSet());
87+
assertFalse(ignoreAbove.valuesPotentiallyIgnored());
8288
}
8389

8490
public void test_ignore_above_default_for_logsdb_indices() {
@@ -88,6 +94,7 @@ public void test_ignore_above_default_for_logsdb_indices() {
8894
// when/then
8995
assertEquals(Mapper.IgnoreAbove.IGNORE_ABOVE_DEFAULT_VALUE_FOR_LOGSDB_INDICES, ignoreAbove.get());
9096
assertFalse(ignoreAbove.isSet());
97+
assertTrue(ignoreAbove.valuesPotentiallyIgnored());
9198
}
9299

93100
public void test_string_isIgnored() {

0 commit comments

Comments
 (0)