Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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/137026.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
pr: 137026
summary: Improve value loading for `match_only_text` mapping
area: ES|QL
type: enhancement
issues: []
Original file line number Diff line number Diff line change
Expand Up @@ -604,6 +604,28 @@ protected String delegatingTo() {
}
}

/*
* TODO: This duplicates code from TextFieldMapper
* If this is a sub-text field try and return the parent's loader. Text
* fields will always be slow to load and if the parent is exact then we
* should use that instead.
*/
String parentField = blContext.parentField(name());
if (parentField != null) {
MappedFieldType parent = blContext.lookup().fieldType(parentField);
if (parent.typeName().equals(KeywordFieldMapper.CONTENT_TYPE)) {
KeywordFieldMapper.KeywordFieldType kwd = (KeywordFieldMapper.KeywordFieldType) parent;
if (kwd.hasNormalizer() == false && (kwd.hasDocValues() || kwd.isStored())) {
return new BlockLoader.Delegating(kwd.blockLoader(blContext)) {
@Override
protected String delegatingTo() {
return kwd.name();
}
};
}
}
}

// fallback to _source (synthetic or not)
SourceValueFetcher fetcher = SourceValueFetcher.toString(blContext.sourcePaths(name()), blContext.indexSettings());
// MatchOnlyText never has norms, so we have to use the field names field
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
import org.elasticsearch.index.mapper.TextSearchInfo;
import org.elasticsearch.index.mapper.extras.MatchOnlyTextFieldMapper.MatchOnlyTextFieldType;
import org.elasticsearch.script.ScriptCompiler;
import org.elasticsearch.search.lookup.SearchLookup;
import org.hamcrest.Matchers;

import java.io.IOException;
Expand Down Expand Up @@ -372,4 +373,36 @@ public void testBlockLoaderDoesNotUseSyntheticSourceDelegateWhenIgnoreAboveIsSet
// verify that we don't delegate anything
assertThat(blockLoader, Matchers.not(Matchers.instanceOf(BlockLoader.Delegating.class)));
}

public void testBlockLoaderDelegateToKeywordFieldWhenSyntheticSourceIsDisabled() {
String parentFieldName = "foo";
String childFieldName = "foo.bar";
// given
KeywordFieldMapper.KeywordFieldType keywordFieldType = new KeywordFieldMapper.KeywordFieldType(
parentFieldName,
true,
true,
Collections.emptyMap()
);

MatchOnlyTextFieldMapper.MatchOnlyTextFieldType ft = new MatchOnlyTextFieldMapper.MatchOnlyTextFieldType(
childFieldName,
new TextSearchInfo(TextFieldMapper.Defaults.FIELD_TYPE, null, Lucene.STANDARD_ANALYZER, Lucene.STANDARD_ANALYZER),
mock(NamedAnalyzer.class),
false,
Collections.emptyMap(),
true,
false,
keywordFieldType
);

var mockedSearchLookup = mock(SearchLookup.class);
when(mockedSearchLookup.fieldType(parentFieldName)).thenReturn(keywordFieldType);

var mockedBlockLoaderContext = mock(MappedFieldType.BlockLoaderContext.class);
when(mockedBlockLoaderContext.parentField(childFieldName)).thenReturn(parentFieldName);
when(mockedBlockLoaderContext.lookup()).thenReturn(mockedSearchLookup);
BlockLoader blockLoader = ft.blockLoader(mockedBlockLoaderContext);
assertThat(blockLoader, Matchers.instanceOf(BlockLoader.Delegating.class));
}
}