Throw a 400 when sorting for all types of range fields

This commit is contained in:
Dimitris Rempapis 2025-07-02 12:22:29 +03:00 committed by GitHub
parent c41922fefb
commit 8ffbf4a976
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 133 additions and 1 deletions

View File

@ -0,0 +1,5 @@
pr: 129725
summary: Throw a 400 when sorting for all types of range fields
area: Search
type: bug
issues: []

View File

@ -0,0 +1,107 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the "Elastic License
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
* Public License v 1"; you may not use this file except in compliance with, at
* your election, the "Elastic License 2.0", the "GNU Affero General Public
* License v3.0 only", or the "Server Side Public License, v 1".
*/
package org.elasticsearch.search.sort;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.index.mapper.RangeType;
import org.elasticsearch.rest.RestStatus;
import org.elasticsearch.test.ESSingleNodeTestCase;
import org.elasticsearch.xcontent.XContentBuilder;
import org.elasticsearch.xcontent.XContentFactory;
import static org.elasticsearch.index.query.QueryBuilders.matchAllQuery;
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertFailures;
import static org.hamcrest.Matchers.containsString;
public class RangeFieldSortIT extends ESSingleNodeTestCase {
private static final String FIELD_NAME = "range";
public void testSortingOnIntegerRangeFieldThrows400() throws Exception {
String indexName = "int_range_index";
createIndex(indexName, FIELD_NAME, RangeType.INTEGER.typeName());
assertFailures(
client().prepareSearch(indexName).setQuery(matchAllQuery()).addSort(SortBuilders.fieldSort(FIELD_NAME).order(SortOrder.ASC)),
RestStatus.BAD_REQUEST,
containsString("Sorting by range field [" + FIELD_NAME + "] is not supported")
);
}
public void testSortingOnLongRangeFieldThrows400() throws Exception {
String indexName = "long_range_index";
createIndex(indexName, FIELD_NAME, RangeType.LONG.typeName());
assertFailures(
client().prepareSearch(indexName).setQuery(matchAllQuery()).addSort(SortBuilders.fieldSort(FIELD_NAME).order(SortOrder.ASC)),
RestStatus.BAD_REQUEST,
containsString("Sorting by range field [" + FIELD_NAME + "] is not supported")
);
}
public void testSortingOnFloatRangeFieldThrows400() throws Exception {
String indexName = "float_range_index";
createIndex(indexName, FIELD_NAME, RangeType.FLOAT.typeName());
assertFailures(
client().prepareSearch(indexName).setQuery(matchAllQuery()).addSort(SortBuilders.fieldSort(FIELD_NAME).order(SortOrder.ASC)),
RestStatus.BAD_REQUEST,
containsString("Sorting by range field [" + FIELD_NAME + "] is not supported")
);
}
public void testSortingOnDoubleRangeFieldThrows400() throws Exception {
String indexName = "double_range_index";
createIndex(indexName, FIELD_NAME, RangeType.DOUBLE.typeName());
assertFailures(
client().prepareSearch(indexName).setQuery(matchAllQuery()).addSort(SortBuilders.fieldSort(FIELD_NAME).order(SortOrder.ASC)),
RestStatus.BAD_REQUEST,
containsString("Sorting by range field [" + FIELD_NAME + "] is not supported")
);
}
public void testSortingOnIpRangeFieldThrows400() throws Exception {
String indexName = "ip_range_index";
createIndex(indexName, FIELD_NAME, RangeType.IP.typeName());
assertFailures(
client().prepareSearch(indexName).setQuery(matchAllQuery()).addSort(SortBuilders.fieldSort(FIELD_NAME).order(SortOrder.ASC)),
RestStatus.BAD_REQUEST,
containsString("Sorting by range field [" + FIELD_NAME + "] is not supported")
);
}
public void testSortingOnDateRangeFieldThrows400() throws Exception {
String indexName = "date_range_index";
createIndex(indexName, FIELD_NAME, RangeType.DATE.typeName());
assertFailures(
client().prepareSearch(indexName).setQuery(matchAllQuery()).addSort(SortBuilders.fieldSort(FIELD_NAME).order(SortOrder.ASC)),
RestStatus.BAD_REQUEST,
containsString("Sorting by range field [" + FIELD_NAME + "] is not supported")
);
}
private void createIndex(String indexName, String rangeFieldName, String rangeFieldType) throws Exception {
int numShards = randomIntBetween(1, 3);
client().admin()
.indices()
.prepareCreate(indexName)
.setSettings(Settings.builder().put("index.number_of_shards", numShards))
.setMapping(createMapping(rangeFieldName, rangeFieldType))
.get();
}
private XContentBuilder createMapping(String fieldName, String fieldType) throws Exception {
return XContentFactory.jsonBuilder()
.startObject()
.startObject("properties")
.startObject(fieldName)
.field("type", fieldType)
.endObject()
.endObject()
.endObject();
}
}

View File

@ -10,6 +10,7 @@
package org.elasticsearch.index.mapper; package org.elasticsearch.index.mapper;
import org.apache.lucene.search.Query; import org.apache.lucene.search.Query;
import org.apache.lucene.search.SortField;
import org.apache.lucene.util.BytesRef; import org.apache.lucene.util.BytesRef;
import org.elasticsearch.ElasticsearchException; import org.elasticsearch.ElasticsearchException;
import org.elasticsearch.common.Explicit; import org.elasticsearch.common.Explicit;
@ -20,13 +21,17 @@ import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.time.DateFormatter; import org.elasticsearch.common.time.DateFormatter;
import org.elasticsearch.common.time.DateMathParser; import org.elasticsearch.common.time.DateMathParser;
import org.elasticsearch.common.util.LocaleUtils; import org.elasticsearch.common.util.LocaleUtils;
import org.elasticsearch.core.Nullable;
import org.elasticsearch.core.Tuple; import org.elasticsearch.core.Tuple;
import org.elasticsearch.features.NodeFeature; import org.elasticsearch.features.NodeFeature;
import org.elasticsearch.index.fielddata.FieldDataContext; import org.elasticsearch.index.fielddata.FieldDataContext;
import org.elasticsearch.index.fielddata.IndexFieldData; import org.elasticsearch.index.fielddata.IndexFieldData;
import org.elasticsearch.index.fielddata.IndexFieldDataCache;
import org.elasticsearch.index.fielddata.plain.BinaryIndexFieldData; import org.elasticsearch.index.fielddata.plain.BinaryIndexFieldData;
import org.elasticsearch.index.query.SearchExecutionContext; import org.elasticsearch.index.query.SearchExecutionContext;
import org.elasticsearch.indices.breaker.CircuitBreakerService;
import org.elasticsearch.search.DocValueFormat; import org.elasticsearch.search.DocValueFormat;
import org.elasticsearch.search.MultiValueMode;
import org.elasticsearch.search.aggregations.support.CoreValuesSourceType; import org.elasticsearch.search.aggregations.support.CoreValuesSourceType;
import org.elasticsearch.xcontent.XContentBuilder; import org.elasticsearch.xcontent.XContentBuilder;
import org.elasticsearch.xcontent.XContentParser; import org.elasticsearch.xcontent.XContentParser;
@ -227,7 +232,22 @@ public class RangeFieldMapper extends FieldMapper {
@Override @Override
public IndexFieldData.Builder fielddataBuilder(FieldDataContext fieldDataContext) { public IndexFieldData.Builder fielddataBuilder(FieldDataContext fieldDataContext) {
failIfNoDocValues(); failIfNoDocValues();
return new BinaryIndexFieldData.Builder(name(), CoreValuesSourceType.RANGE); return new BinaryIndexFieldData.Builder(name(), CoreValuesSourceType.RANGE) {
@Override
public BinaryIndexFieldData build(IndexFieldDataCache cache, CircuitBreakerService breakerService) {
return new BinaryIndexFieldData(name(), CoreValuesSourceType.RANGE) {
@Override
public SortField sortField(
@Nullable Object missingValue,
MultiValueMode sortMode,
XFieldComparatorSource.Nested nested,
boolean reverse
) {
throw new IllegalArgumentException("Sorting by range field [" + name() + "] is not supported");
}
};
}
};
} }
@Override @Override