Skip to content

Commit 8ffbf4a

Browse files
authored
Throw a 400 when sorting for all types of range fields
1 parent c41922f commit 8ffbf4a

File tree

3 files changed

+133
-1
lines changed

3 files changed

+133
-1
lines changed

docs/changelog/129725.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
pr: 129725
2+
summary: Throw a 400 when sorting for all types of range fields
3+
area: Search
4+
type: bug
5+
issues: []
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the "Elastic License
4+
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
5+
* Public License v 1"; you may not use this file except in compliance with, at
6+
* your election, the "Elastic License 2.0", the "GNU Affero General Public
7+
* License v3.0 only", or the "Server Side Public License, v 1".
8+
*/
9+
10+
package org.elasticsearch.search.sort;
11+
12+
import org.elasticsearch.common.settings.Settings;
13+
import org.elasticsearch.index.mapper.RangeType;
14+
import org.elasticsearch.rest.RestStatus;
15+
import org.elasticsearch.test.ESSingleNodeTestCase;
16+
import org.elasticsearch.xcontent.XContentBuilder;
17+
import org.elasticsearch.xcontent.XContentFactory;
18+
19+
import static org.elasticsearch.index.query.QueryBuilders.matchAllQuery;
20+
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertFailures;
21+
import static org.hamcrest.Matchers.containsString;
22+
23+
public class RangeFieldSortIT extends ESSingleNodeTestCase {
24+
25+
private static final String FIELD_NAME = "range";
26+
27+
public void testSortingOnIntegerRangeFieldThrows400() throws Exception {
28+
String indexName = "int_range_index";
29+
createIndex(indexName, FIELD_NAME, RangeType.INTEGER.typeName());
30+
assertFailures(
31+
client().prepareSearch(indexName).setQuery(matchAllQuery()).addSort(SortBuilders.fieldSort(FIELD_NAME).order(SortOrder.ASC)),
32+
RestStatus.BAD_REQUEST,
33+
containsString("Sorting by range field [" + FIELD_NAME + "] is not supported")
34+
);
35+
}
36+
37+
public void testSortingOnLongRangeFieldThrows400() throws Exception {
38+
String indexName = "long_range_index";
39+
createIndex(indexName, FIELD_NAME, RangeType.LONG.typeName());
40+
assertFailures(
41+
client().prepareSearch(indexName).setQuery(matchAllQuery()).addSort(SortBuilders.fieldSort(FIELD_NAME).order(SortOrder.ASC)),
42+
RestStatus.BAD_REQUEST,
43+
containsString("Sorting by range field [" + FIELD_NAME + "] is not supported")
44+
);
45+
}
46+
47+
public void testSortingOnFloatRangeFieldThrows400() throws Exception {
48+
String indexName = "float_range_index";
49+
createIndex(indexName, FIELD_NAME, RangeType.FLOAT.typeName());
50+
assertFailures(
51+
client().prepareSearch(indexName).setQuery(matchAllQuery()).addSort(SortBuilders.fieldSort(FIELD_NAME).order(SortOrder.ASC)),
52+
RestStatus.BAD_REQUEST,
53+
containsString("Sorting by range field [" + FIELD_NAME + "] is not supported")
54+
);
55+
}
56+
57+
public void testSortingOnDoubleRangeFieldThrows400() throws Exception {
58+
String indexName = "double_range_index";
59+
createIndex(indexName, FIELD_NAME, RangeType.DOUBLE.typeName());
60+
assertFailures(
61+
client().prepareSearch(indexName).setQuery(matchAllQuery()).addSort(SortBuilders.fieldSort(FIELD_NAME).order(SortOrder.ASC)),
62+
RestStatus.BAD_REQUEST,
63+
containsString("Sorting by range field [" + FIELD_NAME + "] is not supported")
64+
);
65+
}
66+
67+
public void testSortingOnIpRangeFieldThrows400() throws Exception {
68+
String indexName = "ip_range_index";
69+
createIndex(indexName, FIELD_NAME, RangeType.IP.typeName());
70+
assertFailures(
71+
client().prepareSearch(indexName).setQuery(matchAllQuery()).addSort(SortBuilders.fieldSort(FIELD_NAME).order(SortOrder.ASC)),
72+
RestStatus.BAD_REQUEST,
73+
containsString("Sorting by range field [" + FIELD_NAME + "] is not supported")
74+
);
75+
}
76+
77+
public void testSortingOnDateRangeFieldThrows400() throws Exception {
78+
String indexName = "date_range_index";
79+
createIndex(indexName, FIELD_NAME, RangeType.DATE.typeName());
80+
assertFailures(
81+
client().prepareSearch(indexName).setQuery(matchAllQuery()).addSort(SortBuilders.fieldSort(FIELD_NAME).order(SortOrder.ASC)),
82+
RestStatus.BAD_REQUEST,
83+
containsString("Sorting by range field [" + FIELD_NAME + "] is not supported")
84+
);
85+
}
86+
87+
private void createIndex(String indexName, String rangeFieldName, String rangeFieldType) throws Exception {
88+
int numShards = randomIntBetween(1, 3);
89+
client().admin()
90+
.indices()
91+
.prepareCreate(indexName)
92+
.setSettings(Settings.builder().put("index.number_of_shards", numShards))
93+
.setMapping(createMapping(rangeFieldName, rangeFieldType))
94+
.get();
95+
}
96+
97+
private XContentBuilder createMapping(String fieldName, String fieldType) throws Exception {
98+
return XContentFactory.jsonBuilder()
99+
.startObject()
100+
.startObject("properties")
101+
.startObject(fieldName)
102+
.field("type", fieldType)
103+
.endObject()
104+
.endObject()
105+
.endObject();
106+
}
107+
}

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

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
package org.elasticsearch.index.mapper;
1111

1212
import org.apache.lucene.search.Query;
13+
import org.apache.lucene.search.SortField;
1314
import org.apache.lucene.util.BytesRef;
1415
import org.elasticsearch.ElasticsearchException;
1516
import org.elasticsearch.common.Explicit;
@@ -20,13 +21,17 @@
2021
import org.elasticsearch.common.time.DateFormatter;
2122
import org.elasticsearch.common.time.DateMathParser;
2223
import org.elasticsearch.common.util.LocaleUtils;
24+
import org.elasticsearch.core.Nullable;
2325
import org.elasticsearch.core.Tuple;
2426
import org.elasticsearch.features.NodeFeature;
2527
import org.elasticsearch.index.fielddata.FieldDataContext;
2628
import org.elasticsearch.index.fielddata.IndexFieldData;
29+
import org.elasticsearch.index.fielddata.IndexFieldDataCache;
2730
import org.elasticsearch.index.fielddata.plain.BinaryIndexFieldData;
2831
import org.elasticsearch.index.query.SearchExecutionContext;
32+
import org.elasticsearch.indices.breaker.CircuitBreakerService;
2933
import org.elasticsearch.search.DocValueFormat;
34+
import org.elasticsearch.search.MultiValueMode;
3035
import org.elasticsearch.search.aggregations.support.CoreValuesSourceType;
3136
import org.elasticsearch.xcontent.XContentBuilder;
3237
import org.elasticsearch.xcontent.XContentParser;
@@ -227,7 +232,22 @@ public RangeType rangeType() {
227232
@Override
228233
public IndexFieldData.Builder fielddataBuilder(FieldDataContext fieldDataContext) {
229234
failIfNoDocValues();
230-
return new BinaryIndexFieldData.Builder(name(), CoreValuesSourceType.RANGE);
235+
return new BinaryIndexFieldData.Builder(name(), CoreValuesSourceType.RANGE) {
236+
@Override
237+
public BinaryIndexFieldData build(IndexFieldDataCache cache, CircuitBreakerService breakerService) {
238+
return new BinaryIndexFieldData(name(), CoreValuesSourceType.RANGE) {
239+
@Override
240+
public SortField sortField(
241+
@Nullable Object missingValue,
242+
MultiValueMode sortMode,
243+
XFieldComparatorSource.Nested nested,
244+
boolean reverse
245+
) {
246+
throw new IllegalArgumentException("Sorting by range field [" + name() + "] is not supported");
247+
}
248+
};
249+
}
250+
};
231251
}
232252

233253
@Override

0 commit comments

Comments
 (0)