[Refactor] MapperService to QueryShardContext in valueFetcher (#2027)

* [Refactor] MapperService to QueryShardContext in valueFetcher

QueryShardContext encapsulates MapperService along with other mechanisms useful
for analyzers, highlighters, and readers. This commit refactors the valueFetcher
to use the QueryShardContext as a parameter instead of direct access to the
MapperService. This is an API change. Behavior of the method is unaffected.

Signed-off-by: Nicholas Walter Knize <nknize@apache.org>

* change unnecessary Optional usage

Signed-off-by: Nicholas Walter Knize <nknize@apache.org>

* spotlessApply

Signed-off-by: Nicholas Walter Knize <nknize@apache.org>
This commit is contained in:
Nick Knize 2022-02-08 07:38:20 -06:00 committed by GitHub
parent 343b82fe24
commit 6428d1a2a6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
54 changed files with 196 additions and 141 deletions

View File

@ -135,11 +135,11 @@ public class RankFeatureFieldMapper extends ParametrizedFieldMapper {
} }
@Override @Override
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup searchLookup, String format) { public ValueFetcher valueFetcher(QueryShardContext context, SearchLookup searchLookup, String format) {
if (format != null) { if (format != null) {
throw new IllegalArgumentException("Field [" + name() + "] of type [" + typeName() + "] doesn't support formats."); throw new IllegalArgumentException("Field [" + name() + "] of type [" + typeName() + "] doesn't support formats.");
} }
return new SourceValueFetcher(name(), mapperService) { return new SourceValueFetcher(name(), context) {
@Override @Override
protected Float parseSourceValue(Object value) { protected Float parseSourceValue(Object value) {
return objectToFloat(value); return objectToFloat(value);

View File

@ -65,7 +65,7 @@ public class RankFeatureMetaFieldMapper extends MetadataFieldMapper {
} }
@Override @Override
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup searchLookup, String format) { public ValueFetcher valueFetcher(QueryShardContext context, SearchLookup searchLookup, String format) {
throw new UnsupportedOperationException("Cannot fetch values for internal field [" + typeName() + "]."); throw new UnsupportedOperationException("Cannot fetch values for internal field [" + typeName() + "].");
} }

View File

@ -105,8 +105,8 @@ public class RankFeaturesFieldMapper extends ParametrizedFieldMapper {
} }
@Override @Override
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup searchLookup, String format) { public ValueFetcher valueFetcher(QueryShardContext context, SearchLookup searchLookup, String format) {
return SourceValueFetcher.identity(name(), mapperService, format); return SourceValueFetcher.identity(name(), context, format);
} }
@Override @Override

View File

@ -260,11 +260,11 @@ public class ScaledFloatFieldMapper extends ParametrizedFieldMapper {
} }
@Override @Override
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup searchLookup, String format) { public ValueFetcher valueFetcher(QueryShardContext context, SearchLookup searchLookup, String format) {
if (format != null) { if (format != null) {
throw new IllegalArgumentException("Field [" + name() + "] of type [" + typeName() + "] doesn't support formats."); throw new IllegalArgumentException("Field [" + name() + "] of type [" + typeName() + "] doesn't support formats.");
} }
return new SourceValueFetcher(name(), mapperService) { return new SourceValueFetcher(name(), context) {
@Override @Override
protected Double parseSourceValue(Object value) { protected Double parseSourceValue(Object value) {
double doubleValue; double doubleValue;

View File

@ -329,8 +329,8 @@ public class SearchAsYouTypeFieldMapper extends ParametrizedFieldMapper {
} }
@Override @Override
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup searchLookup, String format) { public ValueFetcher valueFetcher(QueryShardContext context, SearchLookup searchLookup, String format) {
return SourceValueFetcher.toString(name(), mapperService, format); return SourceValueFetcher.toString(name(), context, format);
} }
@Override @Override
@ -439,10 +439,10 @@ public class SearchAsYouTypeFieldMapper extends ParametrizedFieldMapper {
} }
@Override @Override
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup searchLookup, String format) { public ValueFetcher valueFetcher(QueryShardContext context, SearchLookup searchLookup, String format) {
// Because this internal field is modelled as a multi-field, SourceValueFetcher will look up its // Because this internal field is modelled as a multi-field, SourceValueFetcher will look up its
// parent field in _source. So we don't need to use the parent field name here. // parent field in _source. So we don't need to use the parent field name here.
return SourceValueFetcher.toString(name(), mapperService, format); return SourceValueFetcher.toString(name(), context, format);
} }
@Override @Override
@ -545,10 +545,10 @@ public class SearchAsYouTypeFieldMapper extends ParametrizedFieldMapper {
} }
@Override @Override
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup searchLookup, String format) { public ValueFetcher valueFetcher(QueryShardContext context, SearchLookup searchLookup, String format) {
// Because this internal field is modelled as a multi-field, SourceValueFetcher will look up its // Because this internal field is modelled as a multi-field, SourceValueFetcher will look up its
// parent field in _source. So we don't need to use the parent field name here. // parent field in _source. So we don't need to use the parent field name here.
return SourceValueFetcher.toString(name(), mapperService, format); return SourceValueFetcher.toString(name(), context, format);
} }
@Override @Override

View File

@ -36,6 +36,7 @@ import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.TokenStream; import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.analysis.tokenattributes.PositionIncrementAttribute; import org.apache.lucene.analysis.tokenattributes.PositionIncrementAttribute;
import org.opensearch.index.analysis.NamedAnalyzer; import org.opensearch.index.analysis.NamedAnalyzer;
import org.opensearch.index.query.QueryShardContext;
import org.opensearch.search.lookup.SearchLookup; import org.opensearch.search.lookup.SearchLookup;
import java.io.IOException; import java.io.IOException;
@ -119,7 +120,7 @@ public class TokenCountFieldMapper extends ParametrizedFieldMapper {
} }
@Override @Override
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup searchLookup, String format) { public ValueFetcher valueFetcher(QueryShardContext context, SearchLookup searchLookup, String format) {
if (hasDocValues() == false) { if (hasDocValues() == false) {
return lookup -> org.opensearch.common.collect.List.of(); return lookup -> org.opensearch.common.collect.List.of();
} }

View File

@ -39,7 +39,6 @@ import org.apache.lucene.util.BytesRef;
import org.opensearch.index.fielddata.IndexFieldData; import org.opensearch.index.fielddata.IndexFieldData;
import org.opensearch.index.fielddata.plain.SortedSetOrdinalsIndexFieldData; import org.opensearch.index.fielddata.plain.SortedSetOrdinalsIndexFieldData;
import org.opensearch.index.mapper.FieldMapper; import org.opensearch.index.mapper.FieldMapper;
import org.opensearch.index.mapper.MapperService;
import org.opensearch.index.mapper.ParseContext; import org.opensearch.index.mapper.ParseContext;
import org.opensearch.index.mapper.StringFieldType; import org.opensearch.index.mapper.StringFieldType;
import org.opensearch.index.mapper.TextSearchInfo; import org.opensearch.index.mapper.TextSearchInfo;
@ -111,7 +110,7 @@ public class MetaJoinFieldMapper extends FieldMapper {
} }
@Override @Override
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup searchLookup, String format) { public ValueFetcher valueFetcher(QueryShardContext context, SearchLookup searchLookup, String format) {
throw new UnsupportedOperationException("Cannot fetch values for metadata field [" + typeName() + "]."); throw new UnsupportedOperationException("Cannot fetch values for metadata field [" + typeName() + "].");
} }

View File

@ -48,11 +48,11 @@ import org.opensearch.index.fielddata.IndexFieldData;
import org.opensearch.index.fielddata.plain.SortedSetOrdinalsIndexFieldData; import org.opensearch.index.fielddata.plain.SortedSetOrdinalsIndexFieldData;
import org.opensearch.index.mapper.FieldMapper; import org.opensearch.index.mapper.FieldMapper;
import org.opensearch.index.mapper.MappedFieldType; import org.opensearch.index.mapper.MappedFieldType;
import org.opensearch.index.mapper.MapperService;
import org.opensearch.index.mapper.ParseContext; import org.opensearch.index.mapper.ParseContext;
import org.opensearch.index.mapper.StringFieldType; import org.opensearch.index.mapper.StringFieldType;
import org.opensearch.index.mapper.TextSearchInfo; import org.opensearch.index.mapper.TextSearchInfo;
import org.opensearch.index.mapper.ValueFetcher; import org.opensearch.index.mapper.ValueFetcher;
import org.opensearch.index.query.QueryShardContext;
import org.opensearch.search.aggregations.support.CoreValuesSourceType; import org.opensearch.search.aggregations.support.CoreValuesSourceType;
import org.opensearch.search.lookup.SearchLookup; import org.opensearch.search.lookup.SearchLookup;
@ -132,7 +132,7 @@ public final class ParentIdFieldMapper extends FieldMapper {
} }
@Override @Override
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup searchLookup, String format) { public ValueFetcher valueFetcher(QueryShardContext context, SearchLookup searchLookup, String format) {
throw new UnsupportedOperationException("Cannot fetch values for internal field [" + typeName() + "]."); throw new UnsupportedOperationException("Cannot fetch values for internal field [" + typeName() + "].");
} }

View File

@ -57,6 +57,7 @@ import org.opensearch.index.mapper.SourceValueFetcher;
import org.opensearch.index.mapper.StringFieldType; import org.opensearch.index.mapper.StringFieldType;
import org.opensearch.index.mapper.TextSearchInfo; import org.opensearch.index.mapper.TextSearchInfo;
import org.opensearch.index.mapper.ValueFetcher; import org.opensearch.index.mapper.ValueFetcher;
import org.opensearch.index.query.QueryShardContext;
import org.opensearch.search.aggregations.support.CoreValuesSourceType; import org.opensearch.search.aggregations.support.CoreValuesSourceType;
import org.opensearch.search.lookup.SearchLookup; import org.opensearch.search.lookup.SearchLookup;
@ -243,8 +244,8 @@ public final class ParentJoinFieldMapper extends FieldMapper {
} }
@Override @Override
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup searchLookup, String format) { public ValueFetcher valueFetcher(QueryShardContext context, SearchLookup searchLookup, String format) {
return SourceValueFetcher.identity(name(), mapperService, format); return SourceValueFetcher.identity(name(), context, format);
} }
@Override @Override

View File

@ -72,7 +72,6 @@ import org.opensearch.index.mapper.KeywordFieldMapper;
import org.opensearch.index.mapper.MappedFieldType; import org.opensearch.index.mapper.MappedFieldType;
import org.opensearch.index.mapper.Mapper; import org.opensearch.index.mapper.Mapper;
import org.opensearch.index.mapper.MapperParsingException; import org.opensearch.index.mapper.MapperParsingException;
import org.opensearch.index.mapper.MapperService;
import org.opensearch.index.mapper.NumberFieldMapper; import org.opensearch.index.mapper.NumberFieldMapper;
import org.opensearch.index.mapper.ParametrizedFieldMapper; import org.opensearch.index.mapper.ParametrizedFieldMapper;
import org.opensearch.index.mapper.ParseContext; import org.opensearch.index.mapper.ParseContext;
@ -245,8 +244,8 @@ public class PercolatorFieldMapper extends ParametrizedFieldMapper {
} }
@Override @Override
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup searchLookup, String format) { public ValueFetcher valueFetcher(QueryShardContext context, SearchLookup searchLookup, String format) {
return SourceValueFetcher.identity(name(), mapperService, format); return SourceValueFetcher.identity(name(), context, format);
} }
Query percolateQuery( Query percolateQuery(

View File

@ -120,12 +120,12 @@ public class ICUCollationKeywordFieldMapper extends FieldMapper {
} }
@Override @Override
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup searchLookup, String format) { public ValueFetcher valueFetcher(QueryShardContext context, SearchLookup searchLookup, String format) {
if (format != null) { if (format != null) {
throw new IllegalArgumentException("Field [" + name() + "] of type [" + typeName() + "] doesn't support formats."); throw new IllegalArgumentException("Field [" + name() + "] of type [" + typeName() + "] doesn't support formats.");
} }
return new SourceValueFetcher(name(), mapperService, nullValue) { return new SourceValueFetcher(name(), context, nullValue) {
@Override @Override
protected String parseSourceValue(Object value) { protected String parseSourceValue(Object value) {
String keywordValue = value.toString(); String keywordValue = value.toString();

View File

@ -40,8 +40,8 @@ import org.opensearch.index.mapper.DocumentMapper;
import org.opensearch.index.mapper.MappedFieldType; import org.opensearch.index.mapper.MappedFieldType;
import org.opensearch.index.mapper.annotatedtext.AnnotatedTextFieldMapper.AnnotatedHighlighterAnalyzer; import org.opensearch.index.mapper.annotatedtext.AnnotatedTextFieldMapper.AnnotatedHighlighterAnalyzer;
import org.opensearch.index.mapper.annotatedtext.AnnotatedTextFieldMapper.AnnotatedText; import org.opensearch.index.mapper.annotatedtext.AnnotatedTextFieldMapper.AnnotatedText;
import org.opensearch.index.query.QueryShardContext;
import org.opensearch.search.fetch.FetchSubPhase.HitContext; import org.opensearch.search.fetch.FetchSubPhase.HitContext;
import org.opensearch.search.fetch.subphase.highlight.SearchHighlightContext.Field;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
@ -55,12 +55,12 @@ public class AnnotatedTextHighlighter extends UnifiedHighlighter {
@Override @Override
protected List<Object> loadFieldValues( protected List<Object> loadFieldValues(
CustomUnifiedHighlighter highlighter, CustomUnifiedHighlighter highlighter,
QueryShardContext context,
MappedFieldType fieldType, MappedFieldType fieldType,
Field field,
HitContext hitContext, HitContext hitContext,
boolean forceSource boolean forceSource
) throws IOException { ) throws IOException {
List<Object> fieldValues = super.loadFieldValues(highlighter, fieldType, field, hitContext, forceSource); List<Object> fieldValues = super.loadFieldValues(highlighter, context, fieldType, hitContext, forceSource);
List<Object> strings = new ArrayList<>(fieldValues.size()); List<Object> strings = new ArrayList<>(fieldValues.size());
AnnotatedText[] annotations = new AnnotatedText[fieldValues.size()]; AnnotatedText[] annotations = new AnnotatedText[fieldValues.size()];

View File

@ -44,7 +44,6 @@ import org.opensearch.index.fielddata.IndexNumericFieldData.NumericType;
import org.opensearch.index.fielddata.plain.SortedNumericIndexFieldData; import org.opensearch.index.fielddata.plain.SortedNumericIndexFieldData;
import org.opensearch.index.mapper.FieldMapper; import org.opensearch.index.mapper.FieldMapper;
import org.opensearch.index.mapper.MappedFieldType; import org.opensearch.index.mapper.MappedFieldType;
import org.opensearch.index.mapper.MapperService;
import org.opensearch.index.mapper.ParametrizedFieldMapper; import org.opensearch.index.mapper.ParametrizedFieldMapper;
import org.opensearch.index.mapper.ParseContext; import org.opensearch.index.mapper.ParseContext;
import org.opensearch.index.mapper.SourceValueFetcher; import org.opensearch.index.mapper.SourceValueFetcher;
@ -121,8 +120,8 @@ public class Murmur3FieldMapper extends ParametrizedFieldMapper {
} }
@Override @Override
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup searchLookup, String format) { public ValueFetcher valueFetcher(QueryShardContext context, SearchLookup searchLookup, String format) {
return SourceValueFetcher.toString(name(), mapperService, format); return SourceValueFetcher.toString(name(), context, format);
} }
@Override @Override

View File

@ -3523,7 +3523,7 @@ public class HighlighterSearchIT extends OpenSearchIntegTestCase {
assertHitCount(searchResponse, 1); assertHitCount(searchResponse, 1);
HighlightField field = searchResponse.getHits().getAt(0).getHighlightFields().get("keyword"); HighlightField field = searchResponse.getHits().getAt(0).getHighlightFields().get("keyword");
assertThat(field.getFragments().length, equalTo(1)); assertThat(field.getFragments().length, equalTo(1));
assertThat(field.getFragments()[0].string(), equalTo("<em>Hello World</em>")); assertThat(field.getFragments()[0].string(), equalTo("<em>hello world</em>"));
} }
} }

View File

@ -284,19 +284,19 @@ public abstract class AbstractGeometryFieldMapper<Parsed, Processed> extends Fie
} }
@Override @Override
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup searchLookup, String format) { public ValueFetcher valueFetcher(QueryShardContext context, SearchLookup searchLookup, String format) {
String geoFormat = format != null ? format : GeoJsonGeometryFormat.NAME; String geoFormat = format != null ? format : GeoJsonGeometryFormat.NAME;
Function<Object, Object> valueParser = value -> geometryParser.parseAndFormatObject(value, geoFormat); Function<Object, Object> valueParser = value -> geometryParser.parseAndFormatObject(value, geoFormat);
if (parsesArrayValue) { if (parsesArrayValue) {
return new ArraySourceValueFetcher(name(), mapperService) { return new ArraySourceValueFetcher(name(), context) {
@Override @Override
protected Object parseSourceValue(Object value) { protected Object parseSourceValue(Object value) {
return valueParser.apply(value); return valueParser.apply(value);
} }
}; };
} else { } else {
return new SourceValueFetcher(name(), mapperService) { return new SourceValueFetcher(name(), context) {
@Override @Override
protected Object parseSourceValue(Object value) { protected Object parseSourceValue(Object value) {
return valueParser.apply(value); return valueParser.apply(value);

View File

@ -100,7 +100,7 @@ public class AllFieldMapper extends MetadataFieldMapper {
} }
@Override @Override
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup searchLookup, String format) { public ValueFetcher valueFetcher(QueryShardContext context, SearchLookup searchLookup, String format) {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }

View File

@ -33,6 +33,7 @@
package org.opensearch.index.mapper; package org.opensearch.index.mapper;
import org.opensearch.common.Nullable; import org.opensearch.common.Nullable;
import org.opensearch.index.query.QueryShardContext;
import org.opensearch.search.lookup.SourceLookup; import org.opensearch.search.lookup.SourceLookup;
import java.util.ArrayList; import java.util.ArrayList;
@ -51,17 +52,17 @@ public abstract class ArraySourceValueFetcher implements ValueFetcher {
private final Set<String> sourcePaths; private final Set<String> sourcePaths;
private final @Nullable Object nullValue; private final @Nullable Object nullValue;
public ArraySourceValueFetcher(String fieldName, MapperService mapperService) { public ArraySourceValueFetcher(String fieldName, QueryShardContext context) {
this(fieldName, mapperService, null); this(fieldName, context, null);
} }
/** /**
* @param fieldName The name of the field. * @param fieldName The name of the field.
* @param mapperService A mapper service. * @param context A query shard context.
* @param nullValue A optional substitute value if the _source value is 'null'. * @param nullValue A optional substitute value if the _source value is 'null'.
*/ */
public ArraySourceValueFetcher(String fieldName, MapperService mapperService, Object nullValue) { public ArraySourceValueFetcher(String fieldName, QueryShardContext context, Object nullValue) {
this.sourcePaths = mapperService.sourcePath(fieldName); this.sourcePaths = context.sourcePath(fieldName);
this.nullValue = nullValue; this.nullValue = nullValue;
} }

View File

@ -117,8 +117,8 @@ public class BinaryFieldMapper extends ParametrizedFieldMapper {
} }
@Override @Override
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup searchLookup, String format) { public ValueFetcher valueFetcher(QueryShardContext context, SearchLookup searchLookup, String format) {
return SourceValueFetcher.identity(name(), mapperService, format); return SourceValueFetcher.identity(name(), context, format);
} }
@Override @Override

View File

@ -159,12 +159,12 @@ public class BooleanFieldMapper extends ParametrizedFieldMapper {
} }
@Override @Override
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup searchLookup, String format) { public ValueFetcher valueFetcher(QueryShardContext context, SearchLookup searchLookup, String format) {
if (format != null) { if (format != null) {
throw new IllegalArgumentException("Field [" + name() + "] of type [" + typeName() + "] doesn't support formats."); throw new IllegalArgumentException("Field [" + name() + "] of type [" + typeName() + "] doesn't support formats.");
} }
return new SourceValueFetcher(name(), mapperService, nullValue) { return new SourceValueFetcher(name(), context, nullValue) {
@Override @Override
protected Boolean parseSourceValue(Object value) { protected Boolean parseSourceValue(Object value) {
if (value instanceof Boolean) { if (value instanceof Boolean) {

View File

@ -54,6 +54,7 @@ import org.opensearch.common.xcontent.XContentParser.NumberType;
import org.opensearch.common.xcontent.XContentParser.Token; import org.opensearch.common.xcontent.XContentParser.Token;
import org.opensearch.index.analysis.AnalyzerScope; import org.opensearch.index.analysis.AnalyzerScope;
import org.opensearch.index.analysis.NamedAnalyzer; import org.opensearch.index.analysis.NamedAnalyzer;
import org.opensearch.index.query.QueryShardContext;
import org.opensearch.search.lookup.SearchLookup; import org.opensearch.search.lookup.SearchLookup;
import org.opensearch.search.suggest.completion.CompletionSuggester; import org.opensearch.search.suggest.completion.CompletionSuggester;
import org.opensearch.search.suggest.completion.context.ContextMapping; import org.opensearch.search.suggest.completion.context.ContextMapping;
@ -363,12 +364,12 @@ public class CompletionFieldMapper extends ParametrizedFieldMapper {
} }
@Override @Override
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup searchLookup, String format) { public ValueFetcher valueFetcher(QueryShardContext context, SearchLookup searchLookup, String format) {
if (format != null) { if (format != null) {
throw new IllegalArgumentException("Field [" + name() + "] of type [" + typeName() + "] doesn't support formats."); throw new IllegalArgumentException("Field [" + name() + "] of type [" + typeName() + "] doesn't support formats.");
} }
return new ArraySourceValueFetcher(name(), mapperService) { return new ArraySourceValueFetcher(name(), context) {
@Override @Override
protected List<?> parseSourceValue(Object value) { protected List<?> parseSourceValue(Object value) {
if (value instanceof List) { if (value instanceof List) {

View File

@ -66,7 +66,7 @@ public class DataStreamFieldMapper extends MetadataFieldMapper {
} }
@Override @Override
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup searchLookup, String format) { public ValueFetcher valueFetcher(QueryShardContext context, SearchLookup searchLookup, String format) {
throw new UnsupportedOperationException("Cannot fetch values for internal field [" + typeName() + "]"); throw new UnsupportedOperationException("Cannot fetch values for internal field [" + typeName() + "]");
} }

View File

@ -370,13 +370,13 @@ public final class DateFieldMapper extends ParametrizedFieldMapper {
} }
@Override @Override
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup searchLookup, String format) { public ValueFetcher valueFetcher(QueryShardContext context, SearchLookup searchLookup, String format) {
DateFormatter defaultFormatter = dateTimeFormatter(); DateFormatter defaultFormatter = dateTimeFormatter();
DateFormatter formatter = format != null DateFormatter formatter = format != null
? DateFormatter.forPattern(format).withLocale(defaultFormatter.locale()) ? DateFormatter.forPattern(format).withLocale(defaultFormatter.locale())
: defaultFormatter; : defaultFormatter;
return new SourceValueFetcher(name(), mapperService, nullValue) { return new SourceValueFetcher(name(), context, nullValue) {
@Override @Override
public String parseSourceValue(Object value) { public String parseSourceValue(Object value) {
String date = value.toString(); String date = value.toString();

View File

@ -139,7 +139,7 @@ public class FieldNamesFieldMapper extends MetadataFieldMapper {
} }
@Override @Override
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup lookup, String format) { public ValueFetcher valueFetcher(QueryShardContext context, SearchLookup lookup, String format) {
throw new UnsupportedOperationException("Cannot fetch values for internal field [" + name() + "]."); throw new UnsupportedOperationException("Cannot fetch values for internal field [" + name() + "].");
} }

View File

@ -132,7 +132,7 @@ public class IdFieldMapper extends MetadataFieldMapper {
} }
@Override @Override
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup lookup, String format) { public ValueFetcher valueFetcher(QueryShardContext context, SearchLookup lookup, String format) {
throw new UnsupportedOperationException("Cannot fetch values for internal field [" + name() + "]."); throw new UnsupportedOperationException("Cannot fetch values for internal field [" + name() + "].");
} }

View File

@ -90,7 +90,7 @@ public final class IgnoredFieldMapper extends MetadataFieldMapper {
} }
@Override @Override
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup lookup, String format) { public ValueFetcher valueFetcher(QueryShardContext context, SearchLookup lookup, String format) {
throw new UnsupportedOperationException("Cannot fetch values for internal field [" + name() + "]."); throw new UnsupportedOperationException("Cannot fetch values for internal field [" + name() + "].");
} }
} }

View File

@ -86,7 +86,7 @@ public class IndexFieldMapper extends MetadataFieldMapper {
} }
@Override @Override
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup searchLookup, String format) { public ValueFetcher valueFetcher(QueryShardContext context, SearchLookup searchLookup, String format) {
throw new UnsupportedOperationException("Cannot fetch values for internal field [" + name() + "]."); throw new UnsupportedOperationException("Cannot fetch values for internal field [" + name() + "].");
} }
} }

View File

@ -188,11 +188,11 @@ public class IpFieldMapper extends ParametrizedFieldMapper {
} }
@Override @Override
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup searchLookup, String format) { public ValueFetcher valueFetcher(QueryShardContext context, SearchLookup searchLookup, String format) {
if (format != null) { if (format != null) {
throw new IllegalArgumentException("Field [" + name() + "] of type [" + typeName() + "] doesn't support formats."); throw new IllegalArgumentException("Field [" + name() + "] of type [" + typeName() + "] doesn't support formats.");
} }
return new SourceValueFetcher(name(), mapperService, nullValue) { return new SourceValueFetcher(name(), context, nullValue) {
@Override @Override
protected Object parseSourceValue(Object value) { protected Object parseSourceValue(Object value) {
InetAddress address; InetAddress address;

View File

@ -45,6 +45,7 @@ import org.opensearch.index.analysis.IndexAnalyzers;
import org.opensearch.index.analysis.NamedAnalyzer; import org.opensearch.index.analysis.NamedAnalyzer;
import org.opensearch.index.fielddata.IndexFieldData; import org.opensearch.index.fielddata.IndexFieldData;
import org.opensearch.index.fielddata.plain.SortedSetOrdinalsIndexFieldData; import org.opensearch.index.fielddata.plain.SortedSetOrdinalsIndexFieldData;
import org.opensearch.index.query.QueryShardContext;
import org.opensearch.index.similarity.SimilarityProvider; import org.opensearch.index.similarity.SimilarityProvider;
import org.opensearch.search.aggregations.support.CoreValuesSourceType; import org.opensearch.search.aggregations.support.CoreValuesSourceType;
import org.opensearch.search.lookup.SearchLookup; import org.opensearch.search.lookup.SearchLookup;
@ -289,12 +290,12 @@ public final class KeywordFieldMapper extends ParametrizedFieldMapper {
} }
@Override @Override
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup searchLookup, String format) { public ValueFetcher valueFetcher(QueryShardContext context, SearchLookup searchLookup, String format) {
if (format != null) { if (format != null) {
throw new IllegalArgumentException("Field [" + name() + "] of type [" + typeName() + "] doesn't support formats."); throw new IllegalArgumentException("Field [" + name() + "] of type [" + typeName() + "] doesn't support formats.");
} }
return new SourceValueFetcher(name(), mapperService, nullValue) { return new SourceValueFetcher(name(), context, nullValue) {
@Override @Override
protected String parseSourceValue(Object value) { protected String parseSourceValue(Object value) {
String keywordValue = value.toString(); String keywordValue = value.toString();

View File

@ -126,7 +126,7 @@ public abstract class MappedFieldType {
* for metadata fields, field types should not throw {@link UnsupportedOperationException} since this * for metadata fields, field types should not throw {@link UnsupportedOperationException} since this
* could cause a search retrieving multiple fields (like "fields": ["*"]) to fail. * could cause a search retrieving multiple fields (like "fields": ["*"]) to fail.
*/ */
public abstract ValueFetcher valueFetcher(MapperService mapperService, SearchLookup searchLookup, @Nullable String format); public abstract ValueFetcher valueFetcher(QueryShardContext context, SearchLookup searchLookup, @Nullable String format);
/** Returns the name of this type, as would be specified in mapping properties */ /** Returns the name of this type, as would be specified in mapping properties */
public abstract String typeName(); public abstract String typeName();

View File

@ -1062,12 +1062,12 @@ public class NumberFieldMapper extends ParametrizedFieldMapper {
} }
@Override @Override
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup searchLookup, String format) { public ValueFetcher valueFetcher(QueryShardContext context, SearchLookup searchLookup, String format) {
if (format != null) { if (format != null) {
throw new IllegalArgumentException("Field [" + name() + "] of type [" + typeName() + "] doesn't support formats."); throw new IllegalArgumentException("Field [" + name() + "] of type [" + typeName() + "] doesn't support formats.");
} }
return new SourceValueFetcher(name(), mapperService, nullValue) { return new SourceValueFetcher(name(), context, nullValue) {
@Override @Override
protected Object parseSourceValue(Object value) { protected Object parseSourceValue(Object value) {
if (value.equals("")) { if (value.equals("")) {

View File

@ -263,13 +263,13 @@ public class RangeFieldMapper extends ParametrizedFieldMapper {
} }
@Override @Override
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup searchLookup, String format) { public ValueFetcher valueFetcher(QueryShardContext context, SearchLookup searchLookup, String format) {
DateFormatter defaultFormatter = dateTimeFormatter(); DateFormatter defaultFormatter = dateTimeFormatter();
DateFormatter formatter = format != null DateFormatter formatter = format != null
? DateFormatter.forPattern(format).withLocale(defaultFormatter.locale()) ? DateFormatter.forPattern(format).withLocale(defaultFormatter.locale())
: defaultFormatter; : defaultFormatter;
return new SourceValueFetcher(name(), mapperService) { return new SourceValueFetcher(name(), context) {
@Override @Override
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")

View File

@ -36,6 +36,7 @@ import org.apache.lucene.document.Field;
import org.apache.lucene.document.FieldType; import org.apache.lucene.document.FieldType;
import org.apache.lucene.index.IndexOptions; import org.apache.lucene.index.IndexOptions;
import org.opensearch.common.lucene.Lucene; import org.opensearch.common.lucene.Lucene;
import org.opensearch.index.query.QueryShardContext;
import org.opensearch.search.lookup.SearchLookup; import org.opensearch.search.lookup.SearchLookup;
import java.util.Collections; import java.util.Collections;
@ -105,7 +106,7 @@ public class RoutingFieldMapper extends MetadataFieldMapper {
} }
@Override @Override
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup lookup, String format) { public ValueFetcher valueFetcher(QueryShardContext context, SearchLookup lookup, String format) {
throw new UnsupportedOperationException("Cannot fetch values for internal field [" + name() + "]."); throw new UnsupportedOperationException("Cannot fetch values for internal field [" + name() + "].");
} }
} }

View File

@ -138,7 +138,7 @@ public class SeqNoFieldMapper extends MetadataFieldMapper {
} }
@Override @Override
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup lookup, String format) { public ValueFetcher valueFetcher(QueryShardContext context, SearchLookup lookup, String format) {
throw new UnsupportedOperationException("Cannot fetch values for internal field [" + name() + "]."); throw new UnsupportedOperationException("Cannot fetch values for internal field [" + name() + "].");
} }

View File

@ -135,7 +135,7 @@ public class SourceFieldMapper extends MetadataFieldMapper {
} }
@Override @Override
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup lookup, String format) { public ValueFetcher valueFetcher(QueryShardContext context, SearchLookup lookup, String format) {
throw new UnsupportedOperationException("Cannot fetch values for internal field [" + name() + "]."); throw new UnsupportedOperationException("Cannot fetch values for internal field [" + name() + "].");
} }

View File

@ -33,6 +33,7 @@
package org.opensearch.index.mapper; package org.opensearch.index.mapper;
import org.opensearch.common.Nullable; import org.opensearch.common.Nullable;
import org.opensearch.index.query.QueryShardContext;
import org.opensearch.search.lookup.SourceLookup; import org.opensearch.search.lookup.SourceLookup;
import java.util.ArrayDeque; import java.util.ArrayDeque;
@ -52,17 +53,17 @@ public abstract class SourceValueFetcher implements ValueFetcher {
private final Set<String> sourcePaths; private final Set<String> sourcePaths;
private final @Nullable Object nullValue; private final @Nullable Object nullValue;
public SourceValueFetcher(String fieldName, MapperService mapperService) { public SourceValueFetcher(String fieldName, QueryShardContext context) {
this(fieldName, mapperService, null); this(fieldName, context, null);
} }
/** /**
* @param fieldName The name of the field. * @param fieldName The name of the field.
* @param mapperService A mapper service. * @param context A query shard context.
* @param nullValue A optional substitute value if the _source value is 'null'. * @param nullValue A optional substitute value if the _source value is 'null'.
*/ */
public SourceValueFetcher(String fieldName, MapperService mapperService, Object nullValue) { public SourceValueFetcher(String fieldName, QueryShardContext context, Object nullValue) {
this.sourcePaths = mapperService.sourcePath(fieldName); this.sourcePaths = context.sourcePath(fieldName);
this.nullValue = nullValue; this.nullValue = nullValue;
} }
@ -104,11 +105,11 @@ public abstract class SourceValueFetcher implements ValueFetcher {
/** /**
* Creates a {@link SourceValueFetcher} that passes through source values unmodified. * Creates a {@link SourceValueFetcher} that passes through source values unmodified.
*/ */
public static SourceValueFetcher identity(String fieldName, MapperService mapperService, String format) { public static SourceValueFetcher identity(String fieldName, QueryShardContext context, String format) {
if (format != null) { if (format != null) {
throw new IllegalArgumentException("Field [" + fieldName + "] doesn't support formats."); throw new IllegalArgumentException("Field [" + fieldName + "] doesn't support formats.");
} }
return new SourceValueFetcher(fieldName, mapperService) { return new SourceValueFetcher(fieldName, context) {
@Override @Override
protected Object parseSourceValue(Object value) { protected Object parseSourceValue(Object value) {
return value; return value;
@ -119,11 +120,11 @@ public abstract class SourceValueFetcher implements ValueFetcher {
/** /**
* Creates a {@link SourceValueFetcher} that converts source values to strings. * Creates a {@link SourceValueFetcher} that converts source values to strings.
*/ */
public static SourceValueFetcher toString(String fieldName, MapperService mapperService, String format) { public static SourceValueFetcher toString(String fieldName, QueryShardContext context, String format) {
if (format != null) { if (format != null) {
throw new IllegalArgumentException("Field [" + fieldName + "] doesn't support formats."); throw new IllegalArgumentException("Field [" + fieldName + "] doesn't support formats.");
} }
return new SourceValueFetcher(fieldName, mapperService) { return new SourceValueFetcher(fieldName, context) {
@Override @Override
protected Object parseSourceValue(Object value) { protected Object parseSourceValue(Object value) {
return value.toString(); return value.toString();

View File

@ -516,10 +516,10 @@ public class TextFieldMapper extends ParametrizedFieldMapper {
} }
@Override @Override
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup searchLookup, String format) { public ValueFetcher valueFetcher(QueryShardContext context, SearchLookup searchLookup, String format) {
// Because this internal field is modelled as a multi-field, SourceValueFetcher will look up its // Because this internal field is modelled as a multi-field, SourceValueFetcher will look up its
// parent field in _source. So we don't need to use the parent field name here. // parent field in _source. So we don't need to use the parent field name here.
return SourceValueFetcher.toString(name(), mapperService, format); return SourceValueFetcher.toString(name(), context, format);
} }
@Override @Override
@ -546,10 +546,10 @@ public class TextFieldMapper extends ParametrizedFieldMapper {
} }
@Override @Override
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup searchLookup, String format) { public ValueFetcher valueFetcher(QueryShardContext context, SearchLookup searchLookup, String format) {
// Because this internal field is modelled as a multi-field, SourceValueFetcher will look up its // Because this internal field is modelled as a multi-field, SourceValueFetcher will look up its
// parent field in _source. So we don't need to use the parent field name here. // parent field in _source. So we don't need to use the parent field name here.
return SourceValueFetcher.toString(name(), mapperService, format); return SourceValueFetcher.toString(name(), context, format);
} }
void setAnalyzer(NamedAnalyzer delegate) { void setAnalyzer(NamedAnalyzer delegate) {
@ -752,8 +752,8 @@ public class TextFieldMapper extends ParametrizedFieldMapper {
} }
@Override @Override
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup searchLookup, String format) { public ValueFetcher valueFetcher(QueryShardContext context, SearchLookup searchLookup, String format) {
return SourceValueFetcher.toString(name(), mapperService, format); return SourceValueFetcher.toString(name(), context, format);
} }
@Override @Override

View File

@ -106,7 +106,7 @@ public class TypeFieldMapper extends MetadataFieldMapper {
} }
@Override @Override
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup lookup, String format) { public ValueFetcher valueFetcher(QueryShardContext context, SearchLookup lookup, String format) {
throw new UnsupportedOperationException("Cannot fetch values for internal field [" + name() + "]."); throw new UnsupportedOperationException("Cannot fetch values for internal field [" + name() + "].");
} }

View File

@ -69,7 +69,7 @@ public class VersionFieldMapper extends MetadataFieldMapper {
} }
@Override @Override
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup lookup, String format) { public ValueFetcher valueFetcher(QueryShardContext context, SearchLookup lookup, String format) {
throw new UnsupportedOperationException("Cannot fetch values for internal field [" + name() + "]."); throw new UnsupportedOperationException("Cannot fetch values for internal field [" + name() + "].");
} }
} }

View File

@ -295,6 +295,19 @@ public class QueryShardContext extends QueryRewriteContext {
return mapperService.simpleMatchToFullName(pattern); return mapperService.simpleMatchToFullName(pattern);
} }
/**
* Returns the {@link MappedFieldType} for the provided field name.
* If the field is not mapped, the behaviour depends on the index.query.parse.allow_unmapped_fields setting, which defaults to true.
* In case unmapped fields are allowed, null is returned when the field is not mapped.
* In case unmapped fields are not allowed, either an exception is thrown or the field is automatically mapped as a text field.
* @throws QueryShardException if unmapped fields are not allowed and automatically mapping unmapped fields as text is disabled.
* @see QueryShardContext#setAllowUnmappedFields(boolean)
* @see QueryShardContext#setMapUnmappedFieldAsString(boolean)
*/
public MappedFieldType getFieldType(String name) {
return failIfFieldMappingNotFound(name, mapperService.fieldType(name));
}
public MappedFieldType fieldMapper(String name) { public MappedFieldType fieldMapper(String name) {
return failIfFieldMappingNotFound(name, mapperService.fieldType(name)); return failIfFieldMappingNotFound(name, mapperService.fieldType(name));
} }
@ -303,6 +316,14 @@ public class QueryShardContext extends QueryRewriteContext {
return mapperService.getObjectMapper(name); return mapperService.getObjectMapper(name);
} }
public boolean isMetadataField(String field) {
return mapperService.isMetadataField(field);
}
public Set<String> sourcePath(String fullName) {
return mapperService.sourcePath(fullName);
}
/** /**
* Returns s {@link DocumentMapper} instance for the given type. * Returns s {@link DocumentMapper} instance for the given type.
* Delegates to {@link MapperService#documentMapper(String)} * Delegates to {@link MapperService#documentMapper(String)}

View File

@ -36,6 +36,7 @@ import org.apache.lucene.search.Query;
import org.opensearch.index.IndexSettings; import org.opensearch.index.IndexSettings;
import org.opensearch.index.mapper.MapperService; import org.opensearch.index.mapper.MapperService;
import org.opensearch.index.query.ParsedQuery; import org.opensearch.index.query.ParsedQuery;
import org.opensearch.index.query.QueryShardContext;
import org.opensearch.search.SearchExtBuilder; import org.opensearch.search.SearchExtBuilder;
import org.opensearch.search.fetch.subphase.FetchDocValuesContext; import org.opensearch.search.fetch.subphase.FetchDocValuesContext;
import org.opensearch.search.fetch.subphase.FetchFieldsContext; import org.opensearch.search.fetch.subphase.FetchFieldsContext;
@ -220,6 +221,10 @@ public class FetchContext {
return searchContext.getSearchExt(name); return searchContext.getSearchExt(name);
} }
public QueryShardContext getQueryShardContext() {
return searchContext.getQueryShardContext();
}
/** /**
* For a hit document that's being processed, return the source lookup representing the * For a hit document that's being processed, return the source lookup representing the
* root document. This method is used to pass down the root source when processing this * root document. This method is used to pass down the root source when processing this

View File

@ -35,7 +35,6 @@ package org.opensearch.search.fetch.subphase;
import org.apache.lucene.index.LeafReaderContext; import org.apache.lucene.index.LeafReaderContext;
import org.opensearch.common.document.DocumentField; import org.opensearch.common.document.DocumentField;
import org.opensearch.index.mapper.IgnoredFieldMapper; import org.opensearch.index.mapper.IgnoredFieldMapper;
import org.opensearch.index.mapper.MapperService;
import org.opensearch.search.SearchHit; import org.opensearch.search.SearchHit;
import org.opensearch.search.fetch.FetchContext; import org.opensearch.search.fetch.FetchContext;
import org.opensearch.search.fetch.FetchSubPhase; import org.opensearch.search.fetch.FetchSubPhase;
@ -61,7 +60,6 @@ public final class FetchFieldsPhase implements FetchSubPhase {
return null; return null;
} }
MapperService mapperService = fetchContext.mapperService();
SearchLookup searchLookup = fetchContext.searchLookup(); SearchLookup searchLookup = fetchContext.searchLookup();
if (fetchContext.mapperService().documentMapper().sourceMapper().enabled() == false) { if (fetchContext.mapperService().documentMapper().sourceMapper().enabled() == false) {
throw new IllegalArgumentException( throw new IllegalArgumentException(
@ -72,7 +70,7 @@ public final class FetchFieldsPhase implements FetchSubPhase {
); );
} }
FieldFetcher fieldFetcher = FieldFetcher.create(mapperService, searchLookup, fetchFieldsContext.fields()); FieldFetcher fieldFetcher = FieldFetcher.create(fetchContext.getQueryShardContext(), searchLookup, fetchFieldsContext.fields());
return new FetchSubPhaseProcessor() { return new FetchSubPhaseProcessor() {
@Override @Override
public void setNextReader(LeafReaderContext readerContext) { public void setNextReader(LeafReaderContext readerContext) {

View File

@ -35,8 +35,8 @@ package org.opensearch.search.fetch.subphase;
import org.apache.lucene.index.LeafReaderContext; import org.apache.lucene.index.LeafReaderContext;
import org.opensearch.common.document.DocumentField; import org.opensearch.common.document.DocumentField;
import org.opensearch.index.mapper.MappedFieldType; import org.opensearch.index.mapper.MappedFieldType;
import org.opensearch.index.mapper.MapperService;
import org.opensearch.index.mapper.ValueFetcher; import org.opensearch.index.mapper.ValueFetcher;
import org.opensearch.index.query.QueryShardContext;
import org.opensearch.search.lookup.SearchLookup; import org.opensearch.search.lookup.SearchLookup;
import org.opensearch.search.lookup.SourceLookup; import org.opensearch.search.lookup.SourceLookup;
@ -53,7 +53,7 @@ import java.util.Set;
* Then given a specific document, it can retrieve the corresponding fields from the document's source. * Then given a specific document, it can retrieve the corresponding fields from the document's source.
*/ */
public class FieldFetcher { public class FieldFetcher {
public static FieldFetcher create(MapperService mapperService, SearchLookup searchLookup, Collection<FieldAndFormat> fieldAndFormats) { public static FieldFetcher create(QueryShardContext context, SearchLookup searchLookup, Collection<FieldAndFormat> fieldAndFormats) {
List<FieldContext> fieldContexts = new ArrayList<>(); List<FieldContext> fieldContexts = new ArrayList<>();
@ -61,13 +61,13 @@ public class FieldFetcher {
String fieldPattern = fieldAndFormat.field; String fieldPattern = fieldAndFormat.field;
String format = fieldAndFormat.format; String format = fieldAndFormat.format;
Collection<String> concreteFields = mapperService.simpleMatchToFullName(fieldPattern); Collection<String> concreteFields = context.simpleMatchToIndexNames(fieldPattern);
for (String field : concreteFields) { for (String field : concreteFields) {
MappedFieldType ft = mapperService.fieldType(field); MappedFieldType ft = context.getFieldType(field);
if (ft == null || mapperService.isMetadataField(field)) { if (ft == null || context.isMetadataField(field)) {
continue; continue;
} }
ValueFetcher valueFetcher = ft.valueFetcher(mapperService, searchLookup, format); ValueFetcher valueFetcher = ft.valueFetcher(context, searchLookup, format);
fieldContexts.add(new FieldContext(field, valueFetcher)); fieldContexts.add(new FieldContext(field, valueFetcher));
} }
} }

View File

@ -36,8 +36,9 @@ import org.apache.lucene.search.highlight.Encoder;
import org.apache.lucene.search.highlight.SimpleHTMLEncoder; import org.apache.lucene.search.highlight.SimpleHTMLEncoder;
import org.opensearch.index.fieldvisitor.CustomFieldsVisitor; import org.opensearch.index.fieldvisitor.CustomFieldsVisitor;
import org.opensearch.index.mapper.MappedFieldType; import org.opensearch.index.mapper.MappedFieldType;
import org.opensearch.index.mapper.ValueFetcher;
import org.opensearch.index.query.QueryShardContext;
import org.opensearch.search.fetch.FetchSubPhase; import org.opensearch.search.fetch.FetchSubPhase;
import org.opensearch.search.lookup.SourceLookup;
import java.io.IOException; import java.io.IOException;
import java.util.Collections; import java.util.Collections;
@ -58,24 +59,20 @@ public final class HighlightUtils {
/** /**
* Load field values for highlighting. * Load field values for highlighting.
*/ */
public static List<Object> loadFieldValues(MappedFieldType fieldType, FetchSubPhase.HitContext hitContext, boolean forceSource) public static List<Object> loadFieldValues(
throws IOException { MappedFieldType fieldType,
// percolator needs to always load from source, thus it sets the global force source to true QueryShardContext context,
List<Object> textsToHighlight; FetchSubPhase.HitContext hitContext,
boolean forceSource
) throws IOException {
if (forceSource == false && fieldType.isStored()) { if (forceSource == false && fieldType.isStored()) {
CustomFieldsVisitor fieldVisitor = new CustomFieldsVisitor(singleton(fieldType.name()), false); CustomFieldsVisitor fieldVisitor = new CustomFieldsVisitor(singleton(fieldType.name()), false);
hitContext.reader().document(hitContext.docId(), fieldVisitor); hitContext.reader().document(hitContext.docId(), fieldVisitor);
textsToHighlight = fieldVisitor.fields().get(fieldType.name()); List<Object> textsToHighlight = fieldVisitor.fields().get(fieldType.name());
if (textsToHighlight == null) { return textsToHighlight != null ? textsToHighlight : Collections.emptyList();
// Can happen if the document doesn't have the field to highlight
textsToHighlight = Collections.emptyList();
} }
} else { ValueFetcher fetcher = fieldType.valueFetcher(context, null, null);
SourceLookup sourceLookup = hitContext.sourceLookup(); return fetcher.fetchValues(hitContext.sourceLookup());
textsToHighlight = sourceLookup.extractRawValues(fieldType.name());
}
assert textsToHighlight != null;
return textsToHighlight;
} }
public static class Encoders { public static class Encoders {

View File

@ -49,7 +49,6 @@ import org.apache.lucene.util.BytesRefHash;
import org.apache.lucene.util.CollectionUtil; import org.apache.lucene.util.CollectionUtil;
import org.opensearch.common.text.Text; import org.opensearch.common.text.Text;
import org.opensearch.index.IndexSettings; import org.opensearch.index.IndexSettings;
import org.opensearch.index.mapper.KeywordFieldMapper;
import org.opensearch.index.mapper.MappedFieldType; import org.opensearch.index.mapper.MappedFieldType;
import org.opensearch.search.fetch.FetchContext; import org.opensearch.search.fetch.FetchContext;
import org.opensearch.search.fetch.FetchSubPhase; import org.opensearch.search.fetch.FetchSubPhase;
@ -118,25 +117,13 @@ public class PlainHighlighter implements Highlighter {
ArrayList<TextFragment> fragsList = new ArrayList<>(); ArrayList<TextFragment> fragsList = new ArrayList<>();
List<Object> textsToHighlight; List<Object> textsToHighlight;
Analyzer analyzer = context.mapperService().documentMapper(hitContext.hit().getType()).mappers().indexAnalyzer(); Analyzer analyzer = context.mapperService().documentMapper(hitContext.hit().getType()).mappers().indexAnalyzer();
Integer keywordIgnoreAbove = null;
if (fieldType instanceof KeywordFieldMapper.KeywordFieldType) {
KeywordFieldMapper mapper = (KeywordFieldMapper) context.mapperService()
.documentMapper()
.mappers()
.getMapper(fieldContext.fieldName);
keywordIgnoreAbove = mapper.ignoreAbove();
}
;
final int maxAnalyzedOffset = context.getIndexSettings().getHighlightMaxAnalyzedOffset(); final int maxAnalyzedOffset = context.getIndexSettings().getHighlightMaxAnalyzedOffset();
textsToHighlight = HighlightUtils.loadFieldValues(fieldType, hitContext, fieldContext.forceSource); textsToHighlight = HighlightUtils.loadFieldValues(fieldType, context.getQueryShardContext(), hitContext, fieldContext.forceSource);
for (Object textToHighlight : textsToHighlight) { for (Object textToHighlight : textsToHighlight) {
String text = convertFieldValue(fieldType, textToHighlight); String text = convertFieldValue(fieldType, textToHighlight);
int textLength = text.length(); int textLength = text.length();
if (keywordIgnoreAbove != null && textLength > keywordIgnoreAbove) {
continue; // skip highlighting keyword terms that were ignored during indexing
}
if (textLength > maxAnalyzedOffset) { if (textLength > maxAnalyzedOffset) {
throw new IllegalArgumentException( throw new IllegalArgumentException(
"The length of [" "The length of ["

View File

@ -51,6 +51,7 @@ import org.opensearch.index.mapper.IdFieldMapper;
import org.opensearch.index.mapper.KeywordFieldMapper; import org.opensearch.index.mapper.KeywordFieldMapper;
import org.opensearch.index.mapper.MappedFieldType; import org.opensearch.index.mapper.MappedFieldType;
import org.opensearch.index.mapper.TextSearchInfo; import org.opensearch.index.mapper.TextSearchInfo;
import org.opensearch.index.query.QueryShardContext;
import org.opensearch.search.fetch.FetchSubPhase; import org.opensearch.search.fetch.FetchSubPhase;
import org.opensearch.search.fetch.FetchSubPhase.HitContext; import org.opensearch.search.fetch.FetchSubPhase.HitContext;
@ -88,7 +89,13 @@ public class UnifiedHighlighter implements Highlighter {
FetchSubPhase.HitContext hitContext = fieldContext.hitContext; FetchSubPhase.HitContext hitContext = fieldContext.hitContext;
CheckedSupplier<String, IOException> loadFieldValues = () -> { CheckedSupplier<String, IOException> loadFieldValues = () -> {
List<Object> fieldValues = loadFieldValues(highlighter, fieldType, field, hitContext, fieldContext.forceSource); List<Object> fieldValues = loadFieldValues(
highlighter,
fieldContext.context.getQueryShardContext(),
fieldType,
hitContext,
fieldContext.forceSource
);
if (fieldValues.size() == 0) { if (fieldValues.size() == 0) {
return null; return null;
} }
@ -186,12 +193,12 @@ public class UnifiedHighlighter implements Highlighter {
protected List<Object> loadFieldValues( protected List<Object> loadFieldValues(
CustomUnifiedHighlighter highlighter, CustomUnifiedHighlighter highlighter,
QueryShardContext context,
MappedFieldType fieldType, MappedFieldType fieldType,
SearchHighlightContext.Field field,
FetchSubPhase.HitContext hitContext, FetchSubPhase.HitContext hitContext,
boolean forceSource boolean forceSource
) throws IOException { ) throws IOException {
List<Object> fieldValues = HighlightUtils.loadFieldValues(fieldType, hitContext, forceSource); List<Object> fieldValues = HighlightUtils.loadFieldValues(fieldType, context, hitContext, forceSource);
fieldValues = fieldValues.stream().map((s) -> convertFieldValue(fieldType, s)).collect(Collectors.toList()); fieldValues = fieldValues.stream().map((s) -> convertFieldValue(fieldType, s)).collect(Collectors.toList());
return fieldValues; return fieldValues;
} }

View File

@ -225,7 +225,7 @@ public abstract class AbstractStringFieldDataTestCase extends AbstractFieldDataI
writer.addDocument(d); writer.addDocument(d);
d = new Document(); d = new Document();
d.add(new StringField("_id", "6", Field.Store.NO)); addField(d, "_id", "6");
writer.addDocument(d); writer.addDocument(d);
d = new Document(); d = new Document();

View File

@ -39,6 +39,7 @@ import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
import org.apache.lucene.util.LuceneTestCase; import org.apache.lucene.util.LuceneTestCase;
import org.opensearch.index.analysis.AnalyzerScope; import org.opensearch.index.analysis.AnalyzerScope;
import org.opensearch.index.analysis.NamedAnalyzer; import org.opensearch.index.analysis.NamedAnalyzer;
import org.opensearch.index.query.QueryShardContext;
import org.opensearch.search.lookup.SearchLookup; import org.opensearch.search.lookup.SearchLookup;
import java.io.IOException; import java.io.IOException;
@ -84,7 +85,7 @@ public class DocumentFieldMapperTests extends LuceneTestCase {
} }
@Override @Override
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup searchLookup, String format) { public ValueFetcher valueFetcher(QueryShardContext context, SearchLookup searchLookup, String format) {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }

View File

@ -40,6 +40,7 @@ import org.opensearch.geometry.Point;
import org.opensearch.index.analysis.AnalyzerScope; import org.opensearch.index.analysis.AnalyzerScope;
import org.opensearch.index.analysis.IndexAnalyzers; import org.opensearch.index.analysis.IndexAnalyzers;
import org.opensearch.index.analysis.NamedAnalyzer; import org.opensearch.index.analysis.NamedAnalyzer;
import org.opensearch.index.query.QueryShardContext;
import org.opensearch.search.lookup.SearchLookup; import org.opensearch.search.lookup.SearchLookup;
import java.io.IOException; import java.io.IOException;
@ -137,8 +138,8 @@ public class ExternalMapper extends ParametrizedFieldMapper {
} }
@Override @Override
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup searchLookup, String format) { public ValueFetcher valueFetcher(QueryShardContext context, SearchLookup searchLookup, String format) {
return SourceValueFetcher.identity(name(), mapperService, format); return SourceValueFetcher.identity(name(), context, format);
} }
} }

View File

@ -36,6 +36,7 @@ import org.apache.lucene.document.Field;
import org.apache.lucene.document.FieldType; import org.apache.lucene.document.FieldType;
import org.apache.lucene.index.IndexOptions; import org.apache.lucene.index.IndexOptions;
import org.opensearch.common.lucene.Lucene; import org.opensearch.common.lucene.Lucene;
import org.opensearch.index.query.QueryShardContext;
import org.opensearch.search.lookup.SearchLookup; import org.opensearch.search.lookup.SearchLookup;
import java.io.IOException; import java.io.IOException;
@ -95,8 +96,8 @@ public class FakeStringFieldMapper extends ParametrizedFieldMapper {
} }
@Override @Override
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup searchLookup, String format) { public ValueFetcher valueFetcher(QueryShardContext context, SearchLookup searchLookup, String format) {
return SourceValueFetcher.toString(name(), mapperService, format); return SourceValueFetcher.toString(name(), context, format);
} }
} }

View File

@ -45,7 +45,6 @@ import org.opensearch.common.xcontent.NamedXContentRegistry;
import org.opensearch.common.xcontent.XContentParser; import org.opensearch.common.xcontent.XContentParser;
import org.opensearch.index.mapper.KeywordFieldMapper; import org.opensearch.index.mapper.KeywordFieldMapper;
import org.opensearch.index.mapper.MappedFieldType; import org.opensearch.index.mapper.MappedFieldType;
import org.opensearch.index.mapper.MapperService;
import org.opensearch.index.mapper.NumberFieldMapper; import org.opensearch.index.mapper.NumberFieldMapper;
import org.opensearch.index.mapper.TextSearchInfo; import org.opensearch.index.mapper.TextSearchInfo;
import org.opensearch.index.mapper.ValueFetcher; import org.opensearch.index.mapper.ValueFetcher;
@ -239,7 +238,7 @@ public class CollapseBuilderTests extends AbstractSerializingTestCase<CollapseBu
} }
@Override @Override
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup searchLookup, String format) { public ValueFetcher valueFetcher(QueryShardContext context, SearchLookup searchLookup, String format) {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }

View File

@ -32,13 +32,17 @@
package org.opensearch.search.fetch.subphase; package org.opensearch.search.fetch.subphase;
import org.opensearch.Version;
import org.opensearch.cluster.metadata.IndexMetadata;
import org.opensearch.common.bytes.BytesReference; import org.opensearch.common.bytes.BytesReference;
import org.opensearch.common.document.DocumentField; import org.opensearch.common.document.DocumentField;
import org.opensearch.common.settings.Settings; import org.opensearch.common.settings.Settings;
import org.opensearch.common.xcontent.XContentBuilder; import org.opensearch.common.xcontent.XContentBuilder;
import org.opensearch.common.xcontent.XContentFactory; import org.opensearch.common.xcontent.XContentFactory;
import org.opensearch.index.IndexService; import org.opensearch.index.IndexService;
import org.opensearch.index.IndexSettings;
import org.opensearch.index.mapper.MapperService; import org.opensearch.index.mapper.MapperService;
import org.opensearch.index.query.QueryShardContext;
import org.opensearch.search.lookup.SourceLookup; import org.opensearch.search.lookup.SourceLookup;
import org.opensearch.test.OpenSearchSingleNodeTestCase; import org.opensearch.test.OpenSearchSingleNodeTestCase;
@ -428,20 +432,20 @@ public class FieldFetcherTests extends OpenSearchSingleNodeTestCase {
} }
} }
private Map<String, DocumentField> fetchFields(MapperService mapperService, XContentBuilder source, String fieldPattern) private static Map<String, DocumentField> fetchFields(MapperService mapperService, XContentBuilder source, String fieldPattern)
throws IOException { throws IOException {
List<FieldAndFormat> fields = org.opensearch.common.collect.List.of(new FieldAndFormat(fieldPattern, null)); List<FieldAndFormat> fields = org.opensearch.common.collect.List.of(new FieldAndFormat(fieldPattern, null));
return fetchFields(mapperService, source, fields); return fetchFields(mapperService, source, fields);
} }
private Map<String, DocumentField> fetchFields(MapperService mapperService, XContentBuilder source, List<FieldAndFormat> fields) private static Map<String, DocumentField> fetchFields(MapperService mapperService, XContentBuilder source, List<FieldAndFormat> fields)
throws IOException { throws IOException {
SourceLookup sourceLookup = new SourceLookup(); SourceLookup sourceLookup = new SourceLookup();
sourceLookup.setSource(BytesReference.bytes(source)); sourceLookup.setSource(BytesReference.bytes(source));
FieldFetcher fieldFetcher = FieldFetcher.create(mapperService, null, fields); FieldFetcher fieldFetcher = FieldFetcher.create(createQueryShardContext(mapperService), null, fields);
return fieldFetcher.fetch(sourceLookup, org.opensearch.common.collect.Set.of()); return fieldFetcher.fetch(sourceLookup, org.opensearch.common.collect.Set.of());
} }
@ -480,4 +484,34 @@ public class FieldFetcherTests extends OpenSearchSingleNodeTestCase {
IndexService indexService = createIndex("index", Settings.EMPTY, MapperService.SINGLE_MAPPING_NAME, mapping); IndexService indexService = createIndex("index", Settings.EMPTY, MapperService.SINGLE_MAPPING_NAME, mapping);
return indexService.mapperService(); return indexService.mapperService();
} }
private static QueryShardContext createQueryShardContext(MapperService mapperService) {
Settings settings = Settings.builder()
.put("index.version.created", Version.CURRENT)
.put("index.number_of_shards", 1)
.put("index.number_of_replicas", 0)
.put(IndexMetadata.SETTING_INDEX_UUID, "uuid")
.build();
IndexMetadata indexMetadata = new IndexMetadata.Builder("index").settings(settings).build();
IndexSettings indexSettings = new IndexSettings(indexMetadata, settings);
return new QueryShardContext(
0,
indexSettings,
null,
null,
null,
mapperService,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null
);
}
} }

View File

@ -64,7 +64,6 @@ import org.opensearch.common.xcontent.XContentType;
import org.opensearch.index.IndexSettings; import org.opensearch.index.IndexSettings;
import org.opensearch.index.fielddata.IndexNumericFieldData; import org.opensearch.index.fielddata.IndexNumericFieldData;
import org.opensearch.index.mapper.MappedFieldType; import org.opensearch.index.mapper.MappedFieldType;
import org.opensearch.index.mapper.MapperService;
import org.opensearch.index.mapper.TextSearchInfo; import org.opensearch.index.mapper.TextSearchInfo;
import org.opensearch.index.mapper.ValueFetcher; import org.opensearch.index.mapper.ValueFetcher;
import org.opensearch.index.query.QueryShardContext; import org.opensearch.index.query.QueryShardContext;
@ -163,7 +162,7 @@ public class SliceBuilderTests extends OpenSearchTestCase {
) { ) {
@Override @Override
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup searchLookup, String format) { public ValueFetcher valueFetcher(QueryShardContext context, SearchLookup searchLookup, String format) {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }

View File

@ -64,10 +64,10 @@ public abstract class FieldTypeTestCase extends OpenSearchTestCase {
public static List<?> fetchSourceValue(MappedFieldType fieldType, Object sourceValue, String format) throws IOException { public static List<?> fetchSourceValue(MappedFieldType fieldType, Object sourceValue, String format) throws IOException {
String field = fieldType.name(); String field = fieldType.name();
MapperService mapperService = mock(MapperService.class); QueryShardContext context = mock(QueryShardContext.class);
when(mapperService.sourcePath(field)).thenReturn(org.opensearch.common.collect.Set.of(field)); when(context.sourcePath(field)).thenReturn(org.opensearch.common.collect.Set.of(field));
ValueFetcher fetcher = fieldType.valueFetcher(mapperService, null, format); ValueFetcher fetcher = fieldType.valueFetcher(context, null, format);
SourceLookup lookup = new SourceLookup(); SourceLookup lookup = new SourceLookup();
lookup.setSource(Collections.singletonMap(field, sourceValue)); lookup.setSource(Collections.singletonMap(field, sourceValue));
return fetcher.fetchValues(lookup); return fetcher.fetchValues(lookup);

View File

@ -35,6 +35,7 @@ package org.opensearch.index.mapper;
import org.opensearch.Version; import org.opensearch.Version;
import org.opensearch.cluster.metadata.IndexMetadata; import org.opensearch.cluster.metadata.IndexMetadata;
import org.opensearch.common.settings.Settings; import org.opensearch.common.settings.Settings;
import org.opensearch.index.query.QueryShardContext;
import org.opensearch.search.lookup.SearchLookup; import org.opensearch.search.lookup.SearchLookup;
import java.util.Collections; import java.util.Collections;
@ -77,7 +78,7 @@ public class MockFieldMapper extends ParametrizedFieldMapper {
} }
@Override @Override
public ValueFetcher valueFetcher(MapperService mapperService, SearchLookup searchLookup, String format) { public ValueFetcher valueFetcher(QueryShardContext context, SearchLookup searchLookup, String format) {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
} }