Skip to content

Commit 06caf66

Browse files
Adding support to exclude semantic_text subfields from mapper builders
1 parent e333e78 commit 06caf66

File tree

7 files changed

+60
-40
lines changed

7 files changed

+60
-40
lines changed

server/src/main/java/org/elasticsearch/action/fieldcaps/FieldCapabilitiesFetcher.java

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,8 @@
1414
import org.elasticsearch.core.Nullable;
1515
import org.elasticsearch.index.IndexService;
1616
import org.elasticsearch.index.engine.Engine;
17-
import org.elasticsearch.index.mapper.KeywordFieldMapper;
1817
import org.elasticsearch.index.mapper.MappedFieldType;
1918
import org.elasticsearch.index.mapper.RuntimeField;
20-
import org.elasticsearch.index.mapper.vectors.DenseVectorFieldMapper;
21-
import org.elasticsearch.index.mapper.vectors.SparseVectorFieldMapper;
2219
import org.elasticsearch.index.query.MatchAllQueryBuilder;
2320
import org.elasticsearch.index.query.QueryBuilder;
2421
import org.elasticsearch.index.query.SearchExecutionContext;
@@ -152,18 +149,6 @@ private FieldCapabilitiesIndexResponse doFetch(
152149
return new FieldCapabilitiesIndexResponse(shardId.getIndexName(), indexMappingHash, responseMap, true, indexMode);
153150
}
154151

155-
/**
156-
* Returns true if the field should be excluded from the field capabilities response.
157-
* This is used to exclude fields that are not useful for the user, such as
158-
* offset_source and inference chunk embeddings.
159-
*/
160-
private static boolean shouldExcludeField(MappedFieldType ft) {
161-
return ft.typeName().equals("offset_source")
162-
|| ((ft instanceof SparseVectorFieldMapper.SparseVectorFieldType
163-
|| ft instanceof DenseVectorFieldMapper.DenseVectorFieldType
164-
|| ft instanceof KeywordFieldMapper.KeywordFieldType) && ft.name().contains(".inference.chunks"));
165-
}
166-
167152
static Map<String, IndexFieldCapabilities> retrieveFieldCaps(
168153
SearchExecutionContext context,
169154
Predicate<String> fieldNameFilter,
@@ -189,7 +174,7 @@ static Map<String, IndexFieldCapabilities> retrieveFieldCaps(
189174
if ((includeEmptyFields || ft.fieldHasValue(fieldInfos))
190175
&& (fieldPredicate.test(ft.name()) || context.isMetadataField(ft.name()))
191176
&& (filter == null || filter.test(ft))
192-
&& shouldExcludeField(ft) == false) {
177+
&& ft.familyTypeName() != null) {
193178
IndexFieldCapabilities fieldCap = new IndexFieldCapabilities(
194179
field,
195180
ft.familyTypeName(),

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

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,7 @@ public static final class Builder extends FieldMapper.DimensionBuilder {
205205
private final IndexVersion indexCreatedVersion;
206206
private final boolean useDocValuesSkipper;
207207
private final SourceKeepMode indexSourceKeepMode;
208+
private boolean excludeFromFieldCaps = false;
208209

209210
public Builder(final String name, final MappingParserContext mappingParserContext) {
210211
this(
@@ -300,6 +301,11 @@ public Builder ignoreAbove(int ignoreAbove) {
300301
return this;
301302
}
302303

304+
public Builder excludeFromFieldCaps(boolean excludeFromFieldCaps) {
305+
this.excludeFromFieldCaps = excludeFromFieldCaps;
306+
return this;
307+
}
308+
303309
Builder normalizer(String normalizerName) {
304310
this.normalizer.setValue(normalizerName);
305311
return this;
@@ -448,10 +454,13 @@ public KeywordFieldMapper build(MapperBuilderContext context) {
448454
indexCreatedVersion,
449455
IndexVersions.SYNTHETIC_SOURCE_STORE_ARRAYS_NATIVELY_KEYWORD
450456
);
457+
458+
KeywordFieldType keywordFieldType = buildFieldType(context, fieldtype);
459+
keywordFieldType.setExcludeFromFieldCaps(excludeFromFieldCaps);
451460
return new KeywordFieldMapper(
452461
leafName(),
453462
fieldtype,
454-
buildFieldType(context, fieldtype),
463+
keywordFieldType,
455464
builderParams(this, context),
456465
context.isSourceSynthetic(),
457466
useDocValuesSkipper,

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

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ public abstract class MappedFieldType {
6868
private final boolean isStored;
6969
private final TextSearchInfo textSearchInfo;
7070
private final Map<String, String> meta;
71+
private boolean excludeFromFieldCaps;
7172

7273
public MappedFieldType(
7374
String name,
@@ -122,7 +123,11 @@ public IndexFieldData.Builder fielddataBuilder(FieldDataContext fieldDataContext
122123

123124
/** Returns the field family type, as used in field capabilities */
124125
public String familyTypeName() {
125-
return typeName();
126+
return excludeFromFieldCaps ? null : typeName();
127+
}
128+
129+
public void setExcludeFromFieldCaps(boolean exclude) {
130+
this.excludeFromFieldCaps = exclude;
126131
}
127132

128133
public String name() {

server/src/main/java/org/elasticsearch/index/mapper/vectors/DenseVectorFieldMapper.java

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,12 @@ public static class Builder extends FieldMapper.Builder {
186186
private final Parameter<Map<String, String>> meta = Parameter.metaParam();
187187

188188
final IndexVersion indexVersionCreated;
189+
private boolean excludeFromFieldCaps = false;
190+
191+
public Builder(String name, IndexVersion indexVersionCreated, boolean excludeFromFieldCaps) {
192+
this(name, indexVersionCreated);
193+
this.excludeFromFieldCaps = excludeFromFieldCaps;
194+
}
189195

190196
public Builder(String name, IndexVersion indexVersionCreated) {
191197
super(name);
@@ -302,21 +308,23 @@ public Builder indexOptions(IndexOptions indexOptions) {
302308

303309
@Override
304310
public DenseVectorFieldMapper build(MapperBuilderContext context) {
311+
DenseVectorFieldType denseVectorFieldType = new DenseVectorFieldType(
312+
context.buildFullName(leafName()),
313+
indexVersionCreated,
314+
elementType.getValue(),
315+
dims.getValue(),
316+
indexed.getValue(),
317+
similarity.getValue(),
318+
indexOptions.getValue(),
319+
meta.getValue()
320+
);
321+
denseVectorFieldType.setExcludeFromFieldCaps(this.excludeFromFieldCaps);
305322
// Validate again here because the dimensions or element type could have been set programmatically,
306323
// which affects index option validity
307324
validate();
308325
return new DenseVectorFieldMapper(
309326
leafName(),
310-
new DenseVectorFieldType(
311-
context.buildFullName(leafName()),
312-
indexVersionCreated,
313-
elementType.getValue(),
314-
dims.getValue(),
315-
indexed.getValue(),
316-
similarity.getValue(),
317-
indexOptions.getValue(),
318-
meta.getValue()
319-
),
327+
denseVectorFieldType,
320328
builderParams(this, context),
321329
indexOptions.getValue(),
322330
indexVersionCreated

server/src/main/java/org/elasticsearch/index/mapper/vectors/SparseVectorFieldMapper.java

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -73,11 +73,17 @@ private static SparseVectorFieldMapper toType(FieldMapper in) {
7373
public static class Builder extends FieldMapper.Builder {
7474
private final Parameter<Boolean> stored = Parameter.storeParam(m -> toType(m).fieldType().isStored(), false);
7575
private final Parameter<Map<String, String>> meta = Parameter.metaParam();
76+
private boolean excludeFromFieldCaps = false;
7677

7778
public Builder(String name) {
7879
super(name);
7980
}
8081

82+
public Builder(String name, boolean excludeFromFieldCaps) {
83+
super(name);
84+
this.excludeFromFieldCaps = excludeFromFieldCaps;
85+
}
86+
8187
public Builder setStored(boolean value) {
8288
stored.setValue(value);
8389
return this;
@@ -90,11 +96,13 @@ protected Parameter<?>[] getParameters() {
9096

9197
@Override
9298
public SparseVectorFieldMapper build(MapperBuilderContext context) {
93-
return new SparseVectorFieldMapper(
94-
leafName(),
95-
new SparseVectorFieldType(context.buildFullName(leafName()), stored.getValue(), meta.getValue()),
96-
builderParams(this, context)
99+
SparseVectorFieldType sparseVectorFieldType = new SparseVectorFieldType(
100+
context.buildFullName(leafName()),
101+
stored.getValue(),
102+
meta.getValue()
97103
);
104+
sparseVectorFieldType.setExcludeFromFieldCaps(excludeFromFieldCaps);
105+
return new SparseVectorFieldMapper(leafName(), sparseVectorFieldType, builderParams(this, context));
98106
}
99107
}
100108

x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/mapper/OffsetSourceFieldMapper.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -119,11 +119,11 @@ protected Parameter<?>[] getParameters() {
119119

120120
@Override
121121
public OffsetSourceFieldMapper build(MapperBuilderContext context) {
122-
return new OffsetSourceFieldMapper(
123-
leafName(),
124-
new OffsetSourceFieldType(context.buildFullName(leafName()), charset.get(), meta.getValue()),
125-
builderParams(this, context)
126-
);
122+
OffsetSourceFieldType fieldType = new OffsetSourceFieldType(context.buildFullName(leafName()), charset.get(), meta.getValue());
123+
// explicitly setting the field type to be not available for field caps
124+
fieldType.setExcludeFromFieldCaps(true);
125+
126+
return new OffsetSourceFieldMapper(leafName(), fieldType, builderParams(this, context));
127127
}
128128
}
129129

x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/mapper/SemanticTextFieldMapper.java

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1041,7 +1041,9 @@ private static NestedObjectMapper.Builder createChunksField(
10411041
chunksField.add(createEmbeddingsField(indexSettings.getIndexVersionCreated(), modelSettings, useLegacyFormat));
10421042
}
10431043
if (useLegacyFormat) {
1044-
var chunkTextField = new KeywordFieldMapper.Builder(TEXT_FIELD, indexVersionCreated).indexed(false).docValues(false);
1044+
var chunkTextField = new KeywordFieldMapper.Builder(TEXT_FIELD, indexVersionCreated).indexed(false)
1045+
.docValues(false)
1046+
.excludeFromFieldCaps(true);
10451047
chunksField.add(chunkTextField);
10461048
} else {
10471049
chunksField.add(new OffsetSourceFieldMapper.Builder(CHUNKED_OFFSET_FIELD));
@@ -1055,11 +1057,14 @@ private static Mapper.Builder createEmbeddingsField(
10551057
boolean useLegacyFormat
10561058
) {
10571059
return switch (modelSettings.taskType()) {
1058-
case SPARSE_EMBEDDING -> new SparseVectorFieldMapper.Builder(CHUNKED_EMBEDDINGS_FIELD).setStored(useLegacyFormat == false);
1060+
case SPARSE_EMBEDDING -> new SparseVectorFieldMapper.Builder(CHUNKED_EMBEDDINGS_FIELD, true).setStored(
1061+
useLegacyFormat == false
1062+
);
10591063
case TEXT_EMBEDDING -> {
10601064
DenseVectorFieldMapper.Builder denseVectorMapperBuilder = new DenseVectorFieldMapper.Builder(
10611065
CHUNKED_EMBEDDINGS_FIELD,
1062-
indexVersionCreated
1066+
indexVersionCreated,
1067+
true
10631068
);
10641069

10651070
SimilarityMeasure similarity = modelSettings.similarity();

0 commit comments

Comments
 (0)