Skip to content
Closed
Show file tree
Hide file tree
Changes from 14 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,7 @@ override sort order settings:
type: text

- match: { error.type: "illegal_argument_exception" }
- match: { error.reason: "index.sort.fields:[] index.sort.order:[asc, asc], size mismatch" }
- match: { error.reason: "index.sort.field:[] index.sort.order:[asc, asc], size mismatch" }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is index.sort.fields renamed to index.sort.field in this error message?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, I see the error message now originates from another place and index setting name is incorrect was incorrect.


---
override sort missing settings:
Expand Down Expand Up @@ -312,7 +312,7 @@ override sort missing settings:
type: text

- match: { error.type: "illegal_argument_exception" }
- match: { error.reason: "index.sort.fields:[] index.sort.missing:[_last, _first], size mismatch" }
- match: { error.reason: "index.sort.field:[] index.sort.missing:[_last, _first], size mismatch" }

---
override sort mode settings:
Expand Down Expand Up @@ -348,7 +348,7 @@ override sort mode settings:
type: text

- match: { error.type: "illegal_argument_exception" }
- match: { error.reason: "index.sort.fields:[] index.sort.mode:[MAX, MAX], size mismatch" }
- match: { error.reason: "index.sort.field:[] index.sort.mode:[MAX, MAX], size mismatch" }

---
override sort field using nested field type in sorting:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -576,3 +576,29 @@ check time_series empty time bound value:
"@timestamp": "2021-09-26T03:09:52.123456789Z",
"metricset": "pod"
}

---
default sort field:
- requires:
cluster_features: ["gte_v8.1.0"]
reason: introduced in 8.1.0

- do:
indices.create:
index: test_index
body:
settings:
index:
mode: time_series
routing_path: foo
time_series:
start_time: 2021-04-28T00:00:00Z
end_time: 2021-04-29T00:00:00Z

- do:
indices.get_settings:
index: test_index
include_defaults: true
- match: { .test_index.settings.index.mode: time_series }
- match: { .test_index.settings.index.sort.field: [ "_tsid", "@timestamp" ] }
- match: { .test_index.settings.index.sort.order: [ "asc", "desc" ] }
31 changes: 28 additions & 3 deletions server/src/main/java/org/elasticsearch/index/IndexMode.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
import org.elasticsearch.index.mapper.TimeSeriesIdFieldMapper;
import org.elasticsearch.index.mapper.TimeSeriesRoutingHashFieldMapper;
import org.elasticsearch.index.mapper.TsidExtractingIdFieldMapper;
import org.elasticsearch.search.sort.SortOrder;

import java.io.IOException;
import java.time.Instant;
Expand Down Expand Up @@ -402,7 +403,7 @@ public SourceFieldMapper.Mode defaultSourceMode() {
}
};

static final String HOST_NAME = "host.name";
public static final String HOST_NAME = "host.name";

private static void validateRoutingPathSettings(Map<Setting<?>, Object> settings) {
settingRequiresTimeSeries(settings, IndexMetadata.INDEX_ROUTING_PATH);
Expand Down Expand Up @@ -451,8 +452,6 @@ private static CompressedXContent createDefaultMapping(boolean includeHostName)
}

private static final List<Setting<?>> TIME_SERIES_UNSUPPORTED = List.of(
IndexSortConfig.INDEX_SORT_FIELD_SETTING,
IndexSortConfig.INDEX_SORT_ORDER_SETTING,
IndexSortConfig.INDEX_SORT_MODE_SETTING,
IndexSortConfig.INDEX_SORT_MISSING_SETTING
);
Expand Down Expand Up @@ -639,6 +638,32 @@ public void provideAdditionalSettings(
}
if (indexMode == LOOKUP) {
additionalSettings.put(IndexMetadata.SETTING_NUMBER_OF_SHARDS, 1);
} else if (indexMode == TIME_SERIES) {
var sortFields = List.of(TimeSeriesIdFieldMapper.NAME, DataStreamTimestampFieldMapper.DEFAULT_PATH);
var sortOrder = List.of(SortOrder.ASC, SortOrder.DESC);

if (IndexSortConfig.INDEX_SORT_FIELD_SETTING.exists(indexTemplateAndCreateRequestSettings)) {
if (IndexSortConfig.INDEX_SORT_FIELD_SETTING.get(indexTemplateAndCreateRequestSettings).equals(sortFields) == false) {
throw new IllegalArgumentException(
tsdbMode() + " is incompatible with [" + IndexSortConfig.INDEX_SORT_FIELD_SETTING.getKey() + "]"
);
}
} else {
additionalSettings.putList(IndexSortConfig.INDEX_SORT_FIELD_SETTING.getKey(), sortFields);
}

if (IndexSortConfig.INDEX_SORT_ORDER_SETTING.exists(indexTemplateAndCreateRequestSettings)) {
if (IndexSortConfig.INDEX_SORT_ORDER_SETTING.get(indexTemplateAndCreateRequestSettings).equals(sortOrder) == false) {
throw new IllegalArgumentException(
tsdbMode() + " is incompatible with [" + IndexSortConfig.INDEX_SORT_ORDER_SETTING.getKey() + "]"
);
}
} else {
additionalSettings.putList(
IndexSortConfig.INDEX_SORT_ORDER_SETTING.getKey(),
sortOrder.stream().map(Object::toString).toList()
);
}
}
}
}
Expand Down
125 changes: 82 additions & 43 deletions server/src/main/java/org/elasticsearch/index/IndexSortConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -102,25 +102,6 @@ public final class IndexSortConfig {
Setting.Property.ServerlessPublic
);

public static final FieldSortSpec[] TIME_SERIES_SORT, TIMESTAMP_SORT, HOSTNAME_TIMESTAMP_SORT, HOSTNAME_TIMESTAMP_BWC_SORT;
static {
FieldSortSpec timeStampSpec = new FieldSortSpec(DataStreamTimestampFieldMapper.DEFAULT_PATH);
timeStampSpec.order = SortOrder.DESC;
TIME_SERIES_SORT = new FieldSortSpec[] { new FieldSortSpec(TimeSeriesIdFieldMapper.NAME), timeStampSpec };
TIMESTAMP_SORT = new FieldSortSpec[] { timeStampSpec };

FieldSortSpec hostnameSpec = new FieldSortSpec(IndexMode.HOST_NAME);
hostnameSpec.order = SortOrder.ASC;
hostnameSpec.missingValue = "_last";
hostnameSpec.mode = MultiValueMode.MIN;
HOSTNAME_TIMESTAMP_SORT = new FieldSortSpec[] { hostnameSpec, timeStampSpec };

// Older indexes use ascending ordering for host name and timestamp.
HOSTNAME_TIMESTAMP_BWC_SORT = new FieldSortSpec[] {
new FieldSortSpec(IndexMode.HOST_NAME),
new FieldSortSpec(DataStreamTimestampFieldMapper.DEFAULT_PATH) };
}

private static String validateMissingValue(String missing) {
if ("_last".equals(missing) == false && "_first".equals(missing) == false) {
throw new IllegalArgumentException("Illegal missing value:[" + missing + "], " + "must be one of [_last, _first]");
Expand All @@ -146,6 +127,85 @@ private static MultiValueMode parseMultiValueMode(String value) {
return mode;
}

private static void checkSizeMismatch(String firstKey, List<?> first, String secondKey, List<?> second) {
if (first.size() != second.size()) {
throw new IllegalArgumentException(firstKey + ":" + first + " " + secondKey + ":" + second + ", size mismatch");
}
}

public static void validateSortSettings(Settings settings) {
List<String> fields = INDEX_SORT_FIELD_SETTING.get(settings);

if (INDEX_SORT_ORDER_SETTING.exists(settings)) {
var order = INDEX_SORT_ORDER_SETTING.get(settings);
checkSizeMismatch(INDEX_SORT_FIELD_SETTING.getKey(), fields, INDEX_SORT_ORDER_SETTING.getKey(), order);
}

if (INDEX_SORT_MODE_SETTING.exists(settings)) {
var mode = INDEX_SORT_MODE_SETTING.get(settings);
checkSizeMismatch(INDEX_SORT_FIELD_SETTING.getKey(), fields, INDEX_SORT_MODE_SETTING.getKey(), mode);
}

if (INDEX_SORT_MISSING_SETTING.exists(settings)) {
var missing = INDEX_SORT_MISSING_SETTING.get(settings);
checkSizeMismatch(INDEX_SORT_FIELD_SETTING.getKey(), fields, INDEX_SORT_MISSING_SETTING.getKey(), missing);
}
}

public static class LegacyIndexSortConfigDefaults {
public static final FieldSortSpec[] TIME_SERIES_SORT, TIMESTAMP_SORT, HOSTNAME_TIMESTAMP_SORT, HOSTNAME_TIMESTAMP_BWC_SORT;

static {
FieldSortSpec timeStampSpec = new FieldSortSpec(DataStreamTimestampFieldMapper.DEFAULT_PATH);
timeStampSpec.order = SortOrder.DESC;
TIME_SERIES_SORT = new FieldSortSpec[] { new FieldSortSpec(TimeSeriesIdFieldMapper.NAME), timeStampSpec };
TIMESTAMP_SORT = new FieldSortSpec[] { timeStampSpec };

FieldSortSpec hostnameSpec = new FieldSortSpec(IndexMode.HOST_NAME);
hostnameSpec.order = SortOrder.ASC;
hostnameSpec.missingValue = "_last";
hostnameSpec.mode = MultiValueMode.MIN;
HOSTNAME_TIMESTAMP_SORT = new FieldSortSpec[] { hostnameSpec, timeStampSpec };

// Older indexes use ascending ordering for host name and timestamp.
HOSTNAME_TIMESTAMP_BWC_SORT = new FieldSortSpec[] {
new FieldSortSpec(IndexMode.HOST_NAME),
new FieldSortSpec(DataStreamTimestampFieldMapper.DEFAULT_PATH) };
}

public static FieldSortSpec[] getLegacyDefaultSortSpecs(IndexSettings indexSettings) {
var version = indexSettings.getIndexVersionCreated();
if (version.onOrAfter(IndexVersions.EXPLICIT_INDEX_SORTING_DEFAULTS)) {
return null;
}

final Settings settings = indexSettings.getSettings();

IndexMode indexMode = indexSettings.getMode();
if (indexMode == IndexMode.TIME_SERIES) {
return TIME_SERIES_SORT;
} else if (indexMode == IndexMode.LOGSDB) {
if (INDEX_SORT_FIELD_SETTING.exists(settings)) {
return null;
}

validateSortSettings(settings);

if (version.onOrAfter(IndexVersions.LOGSB_OPTIONAL_SORTING_ON_HOST_NAME)
|| version.between(
IndexVersions.LOGSB_OPTIONAL_SORTING_ON_HOST_NAME_BACKPORT,
IndexVersions.UPGRADE_TO_LUCENE_10_0_0
)) {
return (IndexSettings.LOGSDB_SORT_ON_HOST_NAME.get(settings)) ? HOSTNAME_TIMESTAMP_SORT : TIMESTAMP_SORT;
} else {
return HOSTNAME_TIMESTAMP_BWC_SORT;
}
}

return null;
}
}

// visible for tests
final FieldSortSpec[] sortSpecs;
private final IndexVersion indexCreatedVersion;
Expand All @@ -158,34 +218,13 @@ public IndexSortConfig(IndexSettings indexSettings) {
this.indexName = indexSettings.getIndex().getName();
this.indexMode = indexSettings.getMode();

if (indexMode == IndexMode.TIME_SERIES) {
sortSpecs = TIME_SERIES_SORT;
var legacyDefaultSortSpecs = LegacyIndexSortConfigDefaults.getLegacyDefaultSortSpecs(indexSettings);
if (legacyDefaultSortSpecs != null) {
this.sortSpecs = legacyDefaultSortSpecs;
return;
}

List<String> fields = INDEX_SORT_FIELD_SETTING.get(settings);
if (indexMode == IndexMode.LOGSDB && INDEX_SORT_FIELD_SETTING.exists(settings) == false) {
if (INDEX_SORT_ORDER_SETTING.exists(settings)) {
var order = INDEX_SORT_ORDER_SETTING.get(settings);
throw new IllegalArgumentException("index.sort.fields:" + fields + " index.sort.order:" + order + ", size mismatch");
}
if (INDEX_SORT_MODE_SETTING.exists(settings)) {
var mode = INDEX_SORT_MODE_SETTING.get(settings);
throw new IllegalArgumentException("index.sort.fields:" + fields + " index.sort.mode:" + mode + ", size mismatch");
}
if (INDEX_SORT_MISSING_SETTING.exists(settings)) {
var missing = INDEX_SORT_MISSING_SETTING.get(settings);
throw new IllegalArgumentException("index.sort.fields:" + fields + " index.sort.missing:" + missing + ", size mismatch");
}
var version = indexSettings.getIndexVersionCreated();
if (version.onOrAfter(IndexVersions.LOGSB_OPTIONAL_SORTING_ON_HOST_NAME)
|| version.between(IndexVersions.LOGSB_OPTIONAL_SORTING_ON_HOST_NAME_BACKPORT, IndexVersions.UPGRADE_TO_LUCENE_10_0_0)) {
sortSpecs = (IndexSettings.LOGSDB_SORT_ON_HOST_NAME.get(settings)) ? HOSTNAME_TIMESTAMP_SORT : TIMESTAMP_SORT;
} else {
sortSpecs = HOSTNAME_TIMESTAMP_BWC_SORT;
}
return;
}
sortSpecs = fields.stream().map(FieldSortSpec::new).toArray(FieldSortSpec[]::new);

if (INDEX_SORT_ORDER_SETTING.exists(settings)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,7 @@ private static Version parseUnchecked(String version) {
public static final IndexVersion TSID_CREATED_DURING_ROUTING = def(9_037_0_00, Version.LUCENE_10_2_2);
public static final IndexVersion UPGRADE_TO_LUCENE_10_3_0 = def(9_038_0_00, Version.LUCENE_10_3_0);
public static final IndexVersion IGNORED_SOURCE_COALESCED_ENTRIES = def(9_039_0_00, Version.LUCENE_10_3_0);
public static final IndexVersion EXPLICIT_INDEX_SORTING_DEFAULTS = def(9_040_0_00, Version.LUCENE_10_3_0);

/*
* STOP! READ THIS FIRST! No, really,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ public class MapperFeatures implements FeatureSpecification {
static final NodeFeature IGNORED_SOURCE_FIELDS_PER_ENTRY = new NodeFeature("mapper.ignored_source_fields_per_entry");
public static final NodeFeature MULTI_FIELD_UNICODE_OPTIMISATION_FIX = new NodeFeature("mapper.multi_field.unicode_optimisation_fix");
static final NodeFeature PATTERN_TEXT_RENAME = new NodeFeature("mapper.pattern_text_rename");
static final NodeFeature PROVIDE_INDEX_SORT_SETTING_DEFAULTS = new NodeFeature("mapper.provide_index_sort_setting_defaults");

@Override
public Set<NodeFeature> getTestFeatures() {
Expand Down Expand Up @@ -89,7 +90,8 @@ public Set<NodeFeature> getTestFeatures() {
IGNORED_SOURCE_FIELDS_PER_ENTRY,
MULTI_FIELD_UNICODE_OPTIMISATION_FIX,
MATCH_ONLY_TEXT_BLOCK_LOADER_FIX,
PATTERN_TEXT_RENAME
PATTERN_TEXT_RENAME,
PROVIDE_INDEX_SORT_SETTING_DEFAULTS
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
import java.util.List;
import java.util.function.IntSupplier;

import static org.elasticsearch.index.IndexSortConfig.TIME_SERIES_SORT;
import static org.elasticsearch.index.IndexSortConfig.LegacyIndexSortConfigDefaults.TIME_SERIES_SORT;

/**
* An IndexSearcher wrapper that executes the searches in time-series indices by traversing them by tsid and timestamp
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,10 @@ public static IndexMetadata newIndexMeta(String name, Settings indexSettings) {
return IndexMetadata.builder(name).settings(indexSettings(IndexVersion.current(), 1, 1).put(indexSettings)).build();
}

public static IndexMetadata newIndexMeta(String name, Settings indexSettings, IndexVersion indexVersion) {
return IndexMetadata.builder(name).settings(indexSettings(indexVersion, 1, 1).put(indexSettings)).build();
}

public void testUpdateDurability() {
IndexMetadata metadata = newIndexMeta(
"index",
Expand Down
Loading