Skip to content
Merged
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
a8d6c64
Default indexed to false for keyword dimension fields
romseygeek Oct 23, 2025
1293cf4
[CI] Auto commit changes from spotless
Oct 23, 2025
553632c
Merge branch 'main' into dimensions/sparse-indexes
felixbarny Oct 23, 2025
40bfeb3
Same for IpFieldMapper
romseygeek Oct 23, 2025
0ca780c
Merge remote-tracking branch 'romseygeek/dimensions/sparse-indexes' i…
romseygeek Oct 23, 2025
54f19a0
[CI] Auto commit changes from spotless
Oct 23, 2025
d059b5f
Merge branch 'main' into dimensions/sparse-indexes
felixbarny Nov 4, 2025
ccc5f32
Merge remote-tracking branch 'origin/main' into dimensions/sparse-ind…
romseygeek Nov 7, 2025
eae14b0
Merge remote-tracking branch 'origin/main' into dimensions/sparse-ind…
romseygeek Nov 11, 2025
12cf479
wip
romseygeek Nov 11, 2025
eb86816
Use IndexType in TermBasedFieldType constructors
romseygeek Nov 11, 2025
e133d94
Merge branch 'kft/constructor-index-type' into dimensions/sparse-indexes
romseygeek Nov 11, 2025
86e5275
Use sparse indexes for dimension fields
romseygeek Nov 12, 2025
c75fd0a
Merge remote-tracking branch 'origin/main' into dimensions/sparse-ind…
romseygeek Nov 12, 2025
1a9b3a8
Merge remote-tracking branch 'origin/main' into dimensions/sparse-ind…
romseygeek Nov 12, 2025
ddd9647
iter
romseygeek Nov 12, 2025
b1c1ab7
Merge remote-tracking branch 'romseygeek/dimensions/sparse-indexes' i…
romseygeek Nov 12, 2025
ef2141a
Merge branch 'main' into dimensions/sparse-indexes
romseygeek Nov 12, 2025
57b0a61
precommit
romseygeek Nov 12, 2025
b8e2e24
Merge remote-tracking branch 'romseygeek/dimensions/sparse-indexes' i…
romseygeek Nov 12, 2025
667953e
iter
romseygeek Nov 12, 2025
38ee47a
iter
romseygeek Nov 12, 2025
59abb1d
Merge remote-tracking branch 'origin/main' into dimensions/sparse-ind…
romseygeek Nov 12, 2025
1780fc5
Merge branch 'main' into dimensions/sparse-indexes
romseygeek Nov 13, 2025
cefc10e
Merge branch 'main' into dimensions/sparse-indexes
romseygeek Nov 13, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -722,7 +722,13 @@ protected void parseCreateField(DocumentParserContext context) throws IOExceptio
}
long scaledValue = encode(doubleValue, scalingFactor);

NumberFieldMapper.NumberType.LONG.addFields(context.doc(), fieldType().name(), scaledValue, indexed, hasDocValues, stored);
NumberFieldMapper.NumberType.LONG.addFields(
context.doc(),
fieldType().name(),
scaledValue,
IndexType.points(indexed, hasDocValues),
stored
);

if (shouldStoreOffsets) {
context.getOffSetContext().recordOffset(offsetsFieldName, scaledValue);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,13 @@ protected void parseCreateField(DocumentParserContext context) throws IOExceptio
tokenCount = countPositions(analyzer, fullPath(), value, enablePositionIncrements);
}

NumberFieldMapper.NumberType.INTEGER.addFields(context.doc(), fieldType().name(), tokenCount, index, hasDocValues, store);
NumberFieldMapper.NumberType.INTEGER.addFields(
context.doc(),
fieldType().name(),
tokenCount,
IndexType.points(index, hasDocValues),
store
);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,7 @@ private static Version parseUnchecked(String version) {
public static final IndexVersion REENABLED_TIMESTAMP_DOC_VALUES_SPARSE_INDEX = def(9_042_0_00, Version.LUCENE_10_3_1);
public static final IndexVersion SKIPPERS_ENABLED_BY_DEFAULT = def(9_043_0_00, Version.LUCENE_10_3_1);
public static final IndexVersion TIME_SERIES_USE_SYNTHETIC_ID = def(9_044_0_00, Version.LUCENE_10_3_1);
public static final IndexVersion TIME_SERIES_DIMENSIONS_USE_SKIPPERS = def(9_045_0_00, Version.LUCENE_10_3_1);

/*
* STOP! READ THIS FIRST! No, really,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ private static BooleanFieldMapper toType(FieldMapper in) {
public static final class Builder extends FieldMapper.DimensionBuilder {

private final Parameter<Boolean> docValues = Parameter.docValuesParam(m -> toType(m).hasDocValues, true);
private final Parameter<Boolean> indexed = Parameter.indexParam(m -> toType(m).indexed, true);
private final Parameter<Boolean> indexed;
private final Parameter<Boolean> stored = Parameter.storeParam(m -> toType(m).stored, false);
private final Parameter<Explicit<Boolean>> ignoreMalformed;
private final Parameter<Boolean> nullValue = new Parameter<>(
Expand Down Expand Up @@ -117,20 +117,9 @@ public Builder(String name, ScriptCompiler scriptCompiler, IndexSettings indexSe
IGNORE_MALFORMED_SETTING.get(indexSettings.getSettings())
);
this.script.precludesParameters(ignoreMalformed, nullValue);
this.dimension = TimeSeriesParams.dimensionParam(m -> toType(m).fieldType().isDimension(), docValues::get);
this.indexed = Parameter.indexParam(m -> toType(m).indexed, indexSettings, dimension);
addScriptValidation(script, indexed, docValues);
this.dimension = TimeSeriesParams.dimensionParam(m -> toType(m).fieldType().isDimension()).addValidator(v -> {
if (v && (indexed.getValue() == false || docValues.getValue() == false)) {
throw new IllegalArgumentException(
"Field ["
+ TimeSeriesParams.TIME_SERIES_DIMENSION_PARAM
+ "] requires that ["
+ indexed.name
+ "] and ["
+ docValues.name
+ "] are true"
);
}
});
}

public Builder dimension(boolean dimension) {
Expand All @@ -152,16 +141,30 @@ protected Parameter<?>[] getParameters() {
dimension };
}

private IndexType indexType() {
if (indexed.get() && indexSettings.getIndexVersionCreated().isLegacyIndexVersion() == false) {
return IndexType.terms(true, docValues.getValue());
}
if (docValues.get() == false) {
return IndexType.NONE;
}
if (dimension.get()
&& indexSettings.useDocValuesSkipper()
&& indexSettings.getIndexVersionCreated().onOrAfter(IndexVersions.TIME_SERIES_DIMENSIONS_USE_SKIPPERS)) {
return IndexType.skippers();
}
return IndexType.docValuesOnly();
}

@Override
public BooleanFieldMapper build(MapperBuilderContext context) {
if (inheritDimensionParameterFromParentObject(context)) {
dimension(true);
}
MappedFieldType ft = new BooleanFieldType(
context.buildFullName(leafName()),
indexed.getValue() && indexSettings.getIndexVersionCreated().isLegacyIndexVersion() == false,
indexType(),
stored.getValue(),
docValues.getValue(),
nullValue.getValue(),
scriptValues(),
meta.getValue(),
Expand Down Expand Up @@ -215,32 +218,27 @@ public static final class BooleanFieldType extends TermBasedFieldType {

public BooleanFieldType(
String name,
boolean isIndexed,
IndexType indexType,
boolean isStored,
boolean hasDocValues,
Boolean nullValue,
FieldValues<Boolean> scriptValues,
Map<String, String> meta,
boolean isDimension,
boolean isSyntheticSource
) {
super(name, IndexType.terms(isIndexed, hasDocValues), isStored, TextSearchInfo.SIMPLE_MATCH_ONLY, meta);
super(name, indexType, isStored, TextSearchInfo.SIMPLE_MATCH_ONLY, meta);
this.nullValue = nullValue;
this.scriptValues = scriptValues;
this.isDimension = isDimension;
this.isSyntheticSource = isSyntheticSource;
}

public BooleanFieldType(String name) {
this(name, true);
}

public BooleanFieldType(String name, boolean isIndexed) {
this(name, isIndexed, true);
this(name, IndexType.terms(true, true));
}

public BooleanFieldType(String name, boolean isIndexed, boolean hasDocValues) {
this(name, isIndexed, isIndexed, hasDocValues, false, null, Collections.emptyMap(), false, false);
public BooleanFieldType(String name, IndexType indexType) {
this(name, indexType, true, false, null, Collections.emptyMap(), false, false);
}

@Override
Expand Down Expand Up @@ -601,7 +599,11 @@ private void indexValue(DocumentParserContext context, Boolean value) {
context.doc().add(new StoredField(fieldType().name(), value ? "T" : "F"));
}
if (hasDocValues) {
context.doc().add(new SortedNumericDocValuesField(fieldType().name(), value ? 1 : 0));
if (fieldType().indexType.hasDocValuesSkipper()) {
context.doc().add(SortedNumericDocValuesField.indexedField(fieldType().name(), value ? 1 : 0));
} else {
context.doc().add(new SortedNumericDocValuesField(fieldType().name(), value ? 1 : 0));
}
} else {
context.addToFieldNames(fieldType().name());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1314,6 +1314,21 @@ public static Parameter<Boolean> indexParam(Function<FieldMapper, Boolean> initi
return Parameter.boolParam("index", false, initializer, defaultValue);
}

public static Parameter<Boolean> indexParam(
Function<FieldMapper, Boolean> initializer,
IndexSettings indexSettings,
Supplier<Boolean> isDimension
) {
return Parameter.boolParam(
"index",
false,
initializer,
() -> isDimension.get() == false
|| indexSettings.useDocValuesSkipper() == false
|| indexSettings.getIndexVersionCreated().before(IndexVersions.TIME_SERIES_DIMENSIONS_USE_SKIPPERS)
);
}

public static Parameter<Boolean> storeParam(Function<FieldMapper, Boolean> initializer, boolean defaultValue) {
return Parameter.boolParam("store", false, initializer, defaultValue);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ public Builder(String name, ScriptCompiler scriptCompiler, IndexSettings indexSe
}
});
// We allow `time_series_dimension` parameter to be parsed, but only allow it to be `false`
this.dimension = TimeSeriesParams.dimensionParam(m -> false).addValidator(v -> {
this.dimension = TimeSeriesParams.dimensionParam(m -> false, () -> true).addValidator(v -> {
if (v) {
throw new IllegalArgumentException(
"Parameter [" + TimeSeriesParams.TIME_SERIES_DIMENSION_PARAM + "] cannot be set to geo_point"
Expand Down
24 changes: 24 additions & 0 deletions server/src/main/java/org/elasticsearch/index/mapper/IndexType.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@

package org.elasticsearch.index.mapper;

import org.apache.lucene.document.FieldType;
import org.apache.lucene.index.DocValuesSkipIndexType;
import org.apache.lucene.index.DocValuesType;
import org.apache.lucene.index.IndexOptions;

import java.util.Objects;

/**
Expand Down Expand Up @@ -118,6 +123,25 @@ public static IndexType terms(boolean isIndexed, boolean hasDocValues) {
return new IndexType(isIndexed, false, false, false, hasDocValues, false);
}

/**
* @return a terms-based IndexType from a lucene FieldType
*/
public static IndexType terms(FieldType fieldType) {
if (fieldType.indexOptions() == IndexOptions.NONE) {
if (fieldType.docValuesType() == DocValuesType.NONE) {
return NONE;
}
if (fieldType.docValuesSkipIndexType() == DocValuesSkipIndexType.NONE) {
return docValuesOnly();
}
return skippers();
}
if (fieldType.docValuesType() == DocValuesType.NONE) {
return terms(true, false);
}
return terms(true, true);
}

/**
* @return an IndexType with docValuesSkippers
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ private static IpFieldMapper toType(FieldMapper in) {

public static final class Builder extends FieldMapper.DimensionBuilder {

private final Parameter<Boolean> indexed = Parameter.indexParam(m -> toType(m).indexed, true);
private final Parameter<Boolean> indexed;
private final Parameter<Boolean> hasDocValues = Parameter.docValuesParam(m -> toType(m).hasDocValues, true);
private final Parameter<Boolean> stored = Parameter.storeParam(m -> toType(m).stored, false);

Expand Down Expand Up @@ -105,20 +105,9 @@ public Builder(String name, ScriptCompiler scriptCompiler, IndexSettings indexSe
IGNORE_MALFORMED_SETTING.get(indexSettings.getSettings())
);
this.script.precludesParameters(nullValue, ignoreMalformed);
this.dimension = TimeSeriesParams.dimensionParam(m -> toType(m).dimension, hasDocValues::get);
this.indexed = Parameter.indexParam(m -> toType(m).indexed, indexSettings, dimension);
addScriptValidation(script, indexed, hasDocValues);
this.dimension = TimeSeriesParams.dimensionParam(m -> toType(m).dimension).addValidator(v -> {
if (v && (indexed.getValue() == false || hasDocValues.getValue() == false)) {
throw new IllegalArgumentException(
"Field ["
+ TimeSeriesParams.TIME_SERIES_DIMENSION_PARAM
+ "] requires that ["
+ indexed.name
+ "] and ["
+ hasDocValues.name
+ "] are true"
);
}
});
}

Builder nullValue(String nullValue) {
Expand Down Expand Up @@ -186,6 +175,11 @@ private IndexType indexType() {
if (indexSettings.getIndexVersionCreated().isLegacyIndexVersion()) {
return hasDocValues.get() ? IndexType.archivedPoints() : IndexType.NONE;
}
if (dimension.get()
&& indexSettings.useDocValuesSkipper()
&& indexSettings.getIndexVersionCreated().onOrAfter(IndexVersions.TIME_SERIES_DIMENSIONS_USE_SKIPPERS)) {
return IndexType.skippers();
}
return IndexType.points(indexed.get(), hasDocValues.get());
}

Expand Down Expand Up @@ -650,7 +644,11 @@ private void indexValue(DocumentParserContext context, ESInetAddressPoint addres
doc.add(address);
}
if (hasDocValues) {
doc.add(new SortedSetDocValuesField(fieldType().name(), address.binaryValue()));
if (indexed == false) {
doc.add(SortedSetDocValuesField.indexedField(fieldType().name(), address.binaryValue()));
} else {
doc.add(new SortedSetDocValuesField(fieldType().name(), address.binaryValue()));
}
} else if (stored || indexed) {
context.addToFieldNames(fieldType().name());
}
Expand Down
Loading