Skip to content

Commit cfae927

Browse files
committed
Added TextFamilyFieldType
1 parent accafb1 commit cfae927

File tree

20 files changed

+169
-126
lines changed

20 files changed

+169
-126
lines changed

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

Lines changed: 27 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,6 @@
5353
import org.elasticsearch.index.mapper.MapperBuilderContext;
5454
import org.elasticsearch.index.mapper.SourceLoader;
5555
import org.elasticsearch.index.mapper.SourceValueFetcher;
56-
import org.elasticsearch.index.mapper.StringFieldType;
5756
import org.elasticsearch.index.mapper.TextFamilyFieldMapper;
5857
import org.elasticsearch.index.mapper.TextFieldMapper;
5958
import org.elasticsearch.index.mapper.TextFieldMapper.TextFieldType;
@@ -141,14 +140,15 @@ private MatchOnlyTextFieldType buildFieldType(MapperBuilderContext context, Mult
141140
NamedAnalyzer indexAnalyzer = analyzers.getIndexAnalyzer();
142141
TextSearchInfo tsi = new TextSearchInfo(Defaults.FIELD_TYPE, null, searchAnalyzer, searchQuoteAnalyzer);
143142
return new MatchOnlyTextFieldType(
144-
context.buildFullName(leafName()),
145-
tsi,
146-
indexAnalyzer,
147-
context.isSourceSynthetic(),
148-
meta.getValue(),
149-
isWithinMultiField,
150-
storedFieldInBinaryFormat,
151-
TextFieldMapper.SyntheticSourceHelper.syntheticSourceDelegate(getFieldType(), multiFields));
143+
context.buildFullName(leafName()),
144+
tsi,
145+
indexAnalyzer,
146+
context.isSourceSynthetic(),
147+
meta.getValue(),
148+
isWithinMultiField,
149+
storedFieldInBinaryFormat,
150+
TextFieldMapper.SyntheticSourceHelper.syntheticSourceDelegate(getFieldType(), multiFields)
151+
);
152152
}
153153

154154
/**
@@ -189,12 +189,10 @@ private static boolean isSyntheticSourceStoredFieldInBinaryFormat(IndexVersion i
189189
)
190190
);
191191

192-
public static class MatchOnlyTextFieldType extends StringFieldType {
192+
public static class MatchOnlyTextFieldType extends TextFamilyFieldType {
193193

194194
private final Analyzer indexAnalyzer;
195195
private final TextFieldType textFieldType;
196-
197-
private final boolean withinMultiField;
198196
private final boolean storedFieldInBinaryFormat;
199197

200198
public MatchOnlyTextFieldType(
@@ -207,11 +205,9 @@ public MatchOnlyTextFieldType(
207205
boolean storedFieldInBinaryFormat,
208206
KeywordFieldMapper.KeywordFieldType syntheticSourceDelegate
209207
) {
210-
super(name, true, false, false, tsi, meta);
208+
super(name, true, false, false, tsi, meta, isSyntheticSource, withinMultiField);
211209
this.indexAnalyzer = Objects.requireNonNull(indexAnalyzer);
212-
// TODO: need to set synthetic source delegate correctly
213-
this.textFieldType = new TextFieldType(name, isSyntheticSource, syntheticSourceDelegate);
214-
this.withinMultiField = withinMultiField;
210+
this.textFieldType = new TextFieldType(name, isSyntheticSource, withinMultiField, syntheticSourceDelegate);
215211
this.storedFieldInBinaryFormat = storedFieldInBinaryFormat;
216212
}
217213

@@ -254,15 +250,15 @@ private IOFunction<LeafReaderContext, CheckedIntFunction<List<Object>, IOExcepti
254250

255251
// if synthetic source is enabled, then fetch the value from one of the valid source providers
256252
if (searchExecutionContext.isSourceSynthetic()) {
257-
if (withinMultiField) {
253+
if (isWithinMultiField) {
258254
// fetch the value from parent
259255
return parentFieldValueFetcher(searchExecutionContext);
260256
} else if (textFieldType.syntheticSourceDelegate().isPresent()) {
261257
// otherwise, if there is a delegate field, fetch the value from it
262258
return delegateFieldValueFetcher(searchExecutionContext, textFieldType.syntheticSourceDelegate().get());
263259
} else {
264260
// otherwise, fetch the value from self
265-
return storedFieldFetcher(name(), syntheticSourceFallbackFieldName(true));
261+
return storedFieldFetcher(name(), syntheticSourceFallbackFieldName());
266262
}
267263
}
268264

@@ -302,7 +298,7 @@ private IOFunction<LeafReaderContext, CheckedIntFunction<List<Object>, IOExcepti
302298
var parent = searchExecutionContext.lookup().fieldType(parentField);
303299

304300
if (parent instanceof KeywordFieldMapper.KeywordFieldType keywordParent && keywordParent.isIgnoreAboveSet()) {
305-
final String parentFieldName = keywordParent.syntheticSourceFallbackFieldName(searchExecutionContext.isSourceSynthetic());
301+
final String parentFieldName = keywordParent.syntheticSourceFallbackFieldName();
306302
if (parent.isStored()) {
307303
return storedFieldFetcher(parentField, parentFieldName);
308304
} else if (parent.hasDocValues()) {
@@ -331,18 +327,20 @@ private IOFunction<LeafReaderContext, CheckedIntFunction<List<Object>, IOExcepti
331327
) {
332328
// because we don't know whether the delegate field will be ignored during parsing, we must also check the current field
333329
String fieldName = name();
334-
String fallbackName = syntheticSourceFallbackFieldName(true);
330+
String fallbackName = syntheticSourceFallbackFieldName();
335331

336332
// delegate field names
337333
String delegateFieldName = keywordDelegate.name();
338-
String delegateFieldFallbackName = keywordDelegate.syntheticSourceFallbackFieldName(true);
334+
String delegateFieldFallbackName = keywordDelegate.syntheticSourceFallbackFieldName();
339335

340336
if (keywordDelegate.isStored()) {
341337
return storedFieldFetcher(delegateFieldName, delegateFieldFallbackName, fieldName, fallbackName);
342338
} else if (keywordDelegate.hasDocValues()) {
343339
var ifd = searchExecutionContext.getForField(keywordDelegate, MappedFieldType.FielddataOperation.SEARCH);
344-
return combineFieldFetchers(docValuesFieldFetcher(ifd),
345-
storedFieldFetcher(delegateFieldFallbackName, fieldName, fallbackName));
340+
return combineFieldFetchers(
341+
docValuesFieldFetcher(ifd),
342+
storedFieldFetcher(delegateFieldFallbackName, fieldName, fallbackName)
343+
);
346344
} else {
347345
assert false : "multi field should either be stored or have doc values";
348346
return sourceFieldValueFetcher(searchExecutionContext);
@@ -576,8 +574,8 @@ protected BytesRef toBytesRef(Object v) {
576574

577575
@Override
578576
public BlockLoader blockLoader(BlockLoaderContext blContext) {
579-
if (textFieldType.isSyntheticSource()) {
580-
final String fieldName = syntheticSourceFallbackFieldName(true);
577+
if (textFieldType.isSyntheticSourceEnabled()) {
578+
final String fieldName = syntheticSourceFallbackFieldName();
581579
if (storedFieldInBinaryFormat) {
582580
return new BlockStoredFieldsReader.BytesFromBytesRefsBlockLoader(fieldName);
583581
} else {
@@ -595,9 +593,9 @@ public IndexFieldData.Builder fielddataBuilder(FieldDataContext fieldDataContext
595593
if (fieldDataContext.fielddataOperation() != FielddataOperation.SCRIPT) {
596594
throw new IllegalArgumentException(CONTENT_TYPE + " fields do not support sorting and aggregations");
597595
}
598-
if (textFieldType.isSyntheticSource()) {
596+
if (textFieldType.isSyntheticSourceEnabled()) {
599597
return (cache, breaker) -> new StoredFieldSortedBinaryIndexFieldData(
600-
syntheticSourceFallbackFieldName(true),
598+
syntheticSourceFallbackFieldName(),
601599
CoreValuesSourceType.KEYWORD,
602600
TextDocValuesField::new
603601
) {
@@ -684,7 +682,7 @@ protected void parseCreateField(DocumentParserContext context) throws IOExceptio
684682
// if the delegate can't support synthetic source for the given value, then store a copy of said value so
685683
// that synthetic source can load it
686684
if (fieldType().textFieldType.canUseSyntheticSourceDelegateForSyntheticSource(value.string()) == false) {
687-
final String fieldName = fieldType().syntheticSourceFallbackFieldName(fieldType().textFieldType.isSyntheticSource());
685+
final String fieldName = fieldType().syntheticSourceFallbackFieldName();
688686
if (storedFieldInBinaryFormat) {
689687
final var bytesRef = new BytesRef(utfBytes.bytes(), utfBytes.offset(), utfBytes.length());
690688
context.doc().add(new StoredField(fieldName, bytesRef));
@@ -716,7 +714,7 @@ private SourceLoader.SyntheticFieldLoader syntheticFieldLoader(String fullFieldN
716714
// on a delegate field if one exists. Because of this uncertainty, we need multiple field loaders.
717715

718716
// first field loader, representing this field
719-
final String fieldName = fieldType().syntheticSourceFallbackFieldName(fieldType().textFieldType.isSyntheticSource());
717+
final String fieldName = fieldType().syntheticSourceFallbackFieldName();
720718
final var thisFieldLayer = new CompositeSyntheticFieldLoader.StoredFieldLayer(fieldName) {
721719
@Override
722720
protected void writeValue(Object value, XContentBuilder b) throws IOException {

plugins/mapper-annotated-text/src/main/java/org/elasticsearch/index/mapper/annotatedtext/AnnotatedTextFieldMapper.java

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ private AnnotatedTextFieldType buildFieldType(FieldType fieldType, MapperBuilder
137137
store.getValue(),
138138
tsi,
139139
context.isSourceSynthetic(),
140+
isWithinMultiField,
140141
TextFieldMapper.SyntheticSourceHelper.syntheticSourceDelegate(fieldType, multiFields),
141142
meta.getValue()
142143
);
@@ -487,15 +488,17 @@ private void emitAnnotation(int firstSpannedTextPosInc, int annotationPosLen) th
487488
}
488489

489490
public static final class AnnotatedTextFieldType extends TextFieldMapper.TextFieldType {
491+
490492
private AnnotatedTextFieldType(
491493
String name,
492494
boolean store,
493495
TextSearchInfo tsi,
494496
boolean isSyntheticSource,
497+
boolean isWithinMultiField,
495498
KeywordFieldMapper.KeywordFieldType syntheticSourceDelegate,
496499
Map<String, String> meta
497500
) {
498-
super(name, true, store, tsi, isSyntheticSource, syntheticSourceDelegate, meta, false, false);
501+
super(name, true, store, tsi, isSyntheticSource, isWithinMultiField, syntheticSourceDelegate, meta, false, false);
499502
}
500503

501504
public AnnotatedTextFieldType(String name, Map<String, String> meta) {
@@ -573,7 +576,7 @@ protected void parseCreateField(DocumentParserContext context) throws IOExceptio
573576
// otherwise, we need to store a copy of this value so that synthetic source can load it
574577
var utfBytes = value.bytes();
575578
var bytesRef = new BytesRef(utfBytes.bytes(), utfBytes.offset(), utfBytes.length());
576-
final String fieldName = fieldType().syntheticSourceFallbackFieldName(true);
579+
final String fieldName = fieldType().syntheticSourceFallbackFieldName();
577580
context.doc().add(new StoredField(fieldName, bytesRef));
578581
}
579582
}
@@ -607,7 +610,7 @@ private SourceLoader.SyntheticFieldLoader syntheticFieldLoader(String fullFieldN
607610
// need to check both this field and the delegate
608611

609612
// first field loader, representing this field
610-
final String fieldName = fieldType().syntheticSourceFallbackFieldName(isSyntheticSourceEnabled);
613+
final String fieldName = fieldType().syntheticSourceFallbackFieldName();
611614
final var thisFieldLayer = new CompositeSyntheticFieldLoader.StoredFieldLayer(fieldName) {
612615
@Override
613616
protected void writeValue(Object value, XContentBuilder b) throws IOException {

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

Lines changed: 24 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -550,16 +550,14 @@ private static boolean indexSortConfigByHostName(final IndexSortConfig indexSort
550550

551551
public static final TypeParser PARSER = createTypeParserWithLegacySupport(Builder::new);
552552

553-
public static final class KeywordFieldType extends StringFieldType {
553+
public static final class KeywordFieldType extends TextFamilyFieldMapper.TextFamilyFieldType {
554554

555555
private final int ignoreAbove;
556556
private final String nullValue;
557557
private final NamedAnalyzer normalizer;
558558
private final boolean eagerGlobalOrdinals;
559559
private final FieldValues<String> scriptValues;
560560
private final boolean isDimension;
561-
private final boolean isSyntheticSource;
562-
private final boolean isWithinMultiField;
563561
private final IndexMode indexMode;
564562
private final IndexSortConfig indexSortConfig;
565563
private final boolean hasDocValuesSkipper;
@@ -579,31 +577,29 @@ public KeywordFieldType(
579577
fieldType.stored(),
580578
builder.hasDocValues.getValue(),
581579
textSearchInfo(fieldType, builder.similarity.getValue(), searchAnalyzer, quoteAnalyzer),
582-
builder.meta.getValue()
580+
builder.meta.getValue(),
581+
isSyntheticSource,
582+
builder.isWithinMultiField
583583
);
584584
this.eagerGlobalOrdinals = builder.eagerGlobalOrdinals.getValue();
585585
this.normalizer = normalizer;
586586
this.ignoreAbove = builder.ignoreAbove.getValue();
587587
this.nullValue = builder.nullValue.getValue();
588588
this.scriptValues = builder.scriptValues();
589589
this.isDimension = builder.dimension.getValue();
590-
this.isSyntheticSource = isSyntheticSource;
591-
this.isWithinMultiField = builder.isWithinMultiField;
592590
this.indexMode = builder.indexMode;
593591
this.indexSortConfig = builder.indexSortConfig;
594592
this.hasDocValuesSkipper = DocValuesSkipIndexType.NONE.equals(fieldType.docValuesSkipIndexType()) == false;
595593
}
596594

597595
public KeywordFieldType(String name, boolean isIndexed, boolean hasDocValues, Map<String, String> meta) {
598-
super(name, isIndexed, false, hasDocValues, TextSearchInfo.SIMPLE_MATCH_ONLY, meta);
596+
super(name, isIndexed, false, hasDocValues, TextSearchInfo.SIMPLE_MATCH_ONLY, meta, false, false);
599597
this.normalizer = Lucene.KEYWORD_ANALYZER;
600598
this.ignoreAbove = Integer.MAX_VALUE;
601599
this.nullValue = null;
602600
this.eagerGlobalOrdinals = false;
603601
this.scriptValues = null;
604602
this.isDimension = false;
605-
this.isSyntheticSource = false;
606-
this.isWithinMultiField = false;
607603
this.indexMode = IndexMode.STANDARD;
608604
this.indexSortConfig = null;
609605
this.hasDocValuesSkipper = false;
@@ -620,31 +616,38 @@ public KeywordFieldType(String name, FieldType fieldType) {
620616
false,
621617
false,
622618
textSearchInfo(fieldType, null, Lucene.KEYWORD_ANALYZER, Lucene.KEYWORD_ANALYZER),
623-
Collections.emptyMap()
619+
Collections.emptyMap(),
620+
false,
621+
false
624622
);
625623
this.normalizer = Lucene.KEYWORD_ANALYZER;
626624
this.ignoreAbove = Integer.MAX_VALUE;
627625
this.nullValue = null;
628626
this.eagerGlobalOrdinals = false;
629627
this.scriptValues = null;
630628
this.isDimension = false;
631-
this.isSyntheticSource = false;
632-
this.isWithinMultiField = false;
633629
this.indexMode = IndexMode.STANDARD;
634630
this.indexSortConfig = null;
635631
this.hasDocValuesSkipper = DocValuesSkipIndexType.NONE.equals(fieldType.docValuesSkipIndexType()) == false;
636632
}
637633

638634
public KeywordFieldType(String name, NamedAnalyzer analyzer) {
639-
super(name, true, false, true, textSearchInfo(Defaults.FIELD_TYPE, null, analyzer, analyzer), Collections.emptyMap());
635+
super(
636+
name,
637+
true,
638+
false,
639+
true,
640+
textSearchInfo(Defaults.FIELD_TYPE, null, analyzer, analyzer),
641+
Collections.emptyMap(),
642+
false,
643+
false
644+
);
640645
this.normalizer = Lucene.KEYWORD_ANALYZER;
641646
this.ignoreAbove = Integer.MAX_VALUE;
642647
this.nullValue = null;
643648
this.eagerGlobalOrdinals = false;
644649
this.scriptValues = null;
645650
this.isDimension = false;
646-
this.isSyntheticSource = false;
647-
this.isWithinMultiField = false;
648651
this.indexMode = IndexMode.STANDARD;
649652
this.indexSortConfig = null;
650653
this.hasDocValuesSkipper = false;
@@ -808,15 +811,15 @@ NamedAnalyzer normalizer() {
808811

809812
@Override
810813
public BlockLoader blockLoader(BlockLoaderContext blContext) {
811-
if (hasDocValues() && (blContext.fieldExtractPreference() != FieldExtractPreference.STORED || isSyntheticSource)) {
814+
if (hasDocValues() && (blContext.fieldExtractPreference() != FieldExtractPreference.STORED || isSyntheticSourceEnabled)) {
812815
return new BlockDocValuesReader.BytesRefsFromOrdsBlockLoader(name());
813816
}
814817
if (isStored()) {
815818
return new BlockStoredFieldsReader.BytesFromBytesRefsBlockLoader(name());
816819
}
817820

818821
// Multi fields don't have fallback synthetic source.
819-
if (isSyntheticSource && blContext.parentField(name()) == null) {
822+
if (isSyntheticSourceEnabled && blContext.parentField(name()) == null) {
820823
return new FallbackSyntheticSourceBlockLoader(fallbackSyntheticSourceBlockLoaderReader(), name()) {
821824
@Override
822825
public Builder builder(BlockFactory factory, int expectedCount) {
@@ -893,7 +896,7 @@ public IndexFieldData.Builder fielddataBuilder(FieldDataContext fieldDataContext
893896
if (hasDocValues()) {
894897
return fieldDataFromDocValues();
895898
}
896-
if (isSyntheticSource) {
899+
if (isSyntheticSourceEnabled) {
897900
if (false == isStored()) {
898901
throw new IllegalStateException(
899902
"keyword field ["
@@ -1223,7 +1226,7 @@ private boolean indexValue(DocumentParserContext context, String value) {
12231226
*/
12241227
private boolean storeIgnoredValuesForSyntheticSource() {
12251228
// skip all fields that are multi-fields
1226-
return fieldType().isSyntheticSource && fieldType().isWithinMultiField == false;
1229+
return fieldType().isSyntheticSourceEnabled && fieldType().isWithinMultiField == false;
12271230
}
12281231

12291232
private boolean indexValue(DocumentParserContext context, XContentString value) {
@@ -1244,7 +1247,7 @@ private boolean indexValue(DocumentParserContext context, XContentString value)
12441247
if (storeIgnoredValuesForSyntheticSource()) {
12451248
var utfBytes = value.bytes();
12461249
var bytesRef = new BytesRef(utfBytes.bytes(), utfBytes.offset(), utfBytes.length());
1247-
final String fieldName = fieldType().syntheticSourceFallbackFieldName(fieldType().isSyntheticSource);
1250+
final String fieldName = fieldType().syntheticSourceFallbackFieldName();
12481251
context.doc().add(new StoredField(fieldName, bytesRef));
12491252
}
12501253
return false;
@@ -1412,7 +1415,7 @@ protected BytesRef preserve(BytesRef value) {
14121415
// if ignore_above is set, then there is a chance that this field will be ignored. In such cases, we save an
14131416
// extra copy of the field for supporting synthetic source. This layer will check that copy.
14141417
if (fieldType().isIgnoreAboveSet()) {
1415-
final String fieldName = fieldType().syntheticSourceFallbackFieldName(fieldType().isSyntheticSource);
1418+
final String fieldName = fieldType().syntheticSourceFallbackFieldName();
14161419
layers.add(new CompositeSyntheticFieldLoader.StoredFieldLayer(fieldName) {
14171420
@Override
14181421
protected void writeValue(Object value, XContentBuilder b) throws IOException {

0 commit comments

Comments
 (0)