Skip to content

Commit cb38008

Browse files
committed
Add support to VALUES aggregation for spatial types
1 parent 1f4f5dd commit cb38008

File tree

6 files changed

+117
-31
lines changed

6 files changed

+117
-31
lines changed

x-pack/plugin/esql/qa/testFixtures/src/main/resources/spatial.csv-spec

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,67 @@ c:long | x:double | y:double
144144
19 | null | null
145145
;
146146

147+
values
148+
required_capability: agg_values_spatial
149+
150+
FROM airports
151+
| WHERE scalerank == 9
152+
| STATS locations=VALUES(location)
153+
;
154+
155+
locations:geo_point
156+
["POINT(75.9570722403652 30.8503598561702)", "POINT(75.9330597710755 17.625415183635)", "POINT(85.3235970368767 23.3177245989962)", "POINT(48.7471065435931 31.3431585560757)", "POINT(78.2172186546348 26.285487697937)", "POINT(42.97109630194 14.7552534413725)", "POINT(75.8092915005895 22.727749187571)", "POINT(73.8105674924689 19.9660205672806)", "POINT(76.8017261105242 30.6707248949667)", "POINT(75.3958432922005 19.8672969621082)", "POINT(72.9878190922305 31.3627435480862)", "POINT(73.3163595376585 54.9576482934059)", "POINT(82.6671524525865 55.0095847136264)", "POINT(35.3018728575279 47.8732635579023)", "POINT(101.446569298441 0.464600872998505)", "POINT(145.243980298582 14.1717712971216)", "POINT(73.4084964764375 61.3401672194481)", "POINT(78.7089578747476 10.7603571306554)", "POINT(63.0279333519181 25.988794590011)", "POINT(66.9487311480949 30.249043186181)", "POINT(60.900708564915 29.4752941956573)", "POINT(112.711418617258 -7.92998002840567)", "POINT(83.5504532124038 53.3633850813046)", "POINT(75.7584828456005 31.4329422397715)", "POINT(79.452002687657 28.4218087161144)", "POINT(73.0320498392002 33.5614146278861)", "POINT(127.495916124681 36.7220227766673)", "POINT(126.810839481226 35.1400051390198)", "POINT(128.637537699933 35.8999277969087)", "POINT(129.355731047528 35.5928957527107)", "POINT(105.176060419161 -5.242566777132)", "POINT(81.7317271462187 25.443522027821)", "POINT(61.5122589740201 55.2977919496055)"]
157+
;
158+
159+
valuesGrouped
160+
required_capability: agg_values_spatial
161+
162+
FROM airports
163+
| WHERE scalerank == 9
164+
| EVAL first_letter = SUBSTRING(abbrev, 0, 1)
165+
| STATS locations=VALUES(location) BY first_letter
166+
| SORT first_letter
167+
| KEEP first_letter, locations
168+
;
169+
170+
first_letter:keyword | locations:geo_point
171+
A | POINT (48.7471065435931 31.3431585560757)
172+
B | POINT (83.5504532124038 53.3633850813046)
173+
C | [POINT (127.495916124681 36.7220227766673), POINT (61.5122589740201 55.2977919496055)]
174+
G | POINT (78.2172186546348 26.285487697937)
175+
H | POINT (42.97109630194 14.7552534413725)
176+
I | [POINT (85.3235970368767 23.3177245989962), POINT (75.8092915005895 22.727749187571), POINT (73.8105674924689 19.9660205672806), POINT (76.8017261105242 30.6707248949667), POINT (75.3958432922005 19.8672969621082), POINT (81.7317271462187 25.443522027821)]
177+
K | POINT (126.810839481226 35.1400051390198)
178+
L | [POINT (75.9570722403652 30.8503598561702), POINT (72.9878190922305 31.3627435480862)]
179+
M | POINT (112.711418617258 -7.92998002840567)
180+
O | [POINT (73.3163595376585 54.9576482934059), POINT (82.6671524525865 55.0095847136264), POINT (35.3018728575279 47.8732635579023), POINT (73.0320498392002 33.5614146278861)]
181+
P | POINT (101.446569298441 0.464600872998505)
182+
R | POINT (145.243980298582 14.1717712971216)
183+
S | [POINT (75.9330597710755 17.625415183635), POINT (73.4084964764375 61.3401672194481)]
184+
T | [POINT (78.7089578747476 10.7603571306554), POINT (63.0279333519181 25.988794590011), POINT (128.637537699933 35.8999277969087)]
185+
U | [POINT (66.9487311480949 30.249043186181), POINT (129.355731047528 35.5928957527107)]
186+
V | [POINT (75.7584828456005 31.4329422397715), POINT (79.452002687657 28.4218087161144)]
187+
W | POINT (105.176060419161 -5.242566777132)
188+
Z | POINT (60.900708564915 29.4752941956573)
189+
;
190+
191+
valuesGroupedByOrdinals
192+
required_capability: agg_values_spatial
193+
194+
FROM airports
195+
| WHERE scalerank == 9
196+
| STATS locations=VALUES(location) BY type
197+
| SORT type
198+
| KEEP type, locations
199+
;
200+
201+
type:keyword | locations:geo_point
202+
major | [POINT (76.8017261105242 30.6707248949667), POINT (127.495916124681 36.7220227766673)]
203+
mid | [POINT (75.9330597710755 17.625415183635), POINT (85.3235970368767 23.3177245989962), POINT (48.7471065435931 31.3431585560757), POINT (78.2172186546348 26.285487697937), POINT (42.97109630194 14.7552534413725), POINT (75.8092915005895 22.727749187571), POINT (73.8105674924689 19.9660205672806), POINT (75.3958432922005 19.8672969621082), POINT (72.9878190922305 31.3627435480862), POINT (73.3163595376585 54.9576482934059), POINT (82.6671524525865 55.0095847136264), POINT (35.3018728575279 47.8732635579023), POINT (101.446569298441 0.464600872998505), POINT (145.243980298582 14.1717712971216), POINT (73.4084964764375 61.3401672194481), POINT (78.7089578747476 10.7603571306554), POINT (63.0279333519181 25.988794590011), POINT (66.9487311480949 30.249043186181), POINT (60.900708564915 29.4752941956573), POINT (112.711418617258 -7.92998002840567), POINT (83.5504532124038 53.3633850813046), POINT (75.7584828456005 31.4329422397715), POINT (126.810839481226 35.1400051390198), POINT (128.637537699933 35.8999277969087), POINT (129.355731047528 35.5928957527107), POINT (105.176060419161 -5.242566777132), POINT (61.5122589740201 55.2977919496055)]
204+
military | [POINT (78.2172186546348 26.285487697937), POINT (76.8017261105242 30.6707248949667), POINT (72.9878190922305 31.3627435480862), POINT (35.3018728575279 47.8732635579023), POINT (112.711418617258 -7.92998002840567), POINT (75.7584828456005 31.4329422397715), POINT (79.452002687657 28.4218087161144), POINT (126.810839481226 35.1400051390198), POINT (81.7317271462187 25.443522027821)]
205+
small | [POINT (75.9570722403652 30.8503598561702), POINT (73.0320498392002 33.5614146278861)]
206+
;
207+
147208
###############################################
148209
# Tests for ST_CENTROID_AGG on GEO_POINT type
149210

x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/EsqlCapabilities.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,11 @@ public enum Cap {
8181
*/
8282
AGG_VALUES,
8383

84+
/**
85+
* Expand the {@code VALUES} agg to cover spatial types.
86+
*/
87+
AGG_VALUES_SPATIAL,
88+
8489
/**
8590
* Does ESQL support async queries.
8691
*/

x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/EsqlTypeResolutions.java

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -63,12 +63,6 @@ public static Expression.TypeResolution isExact(Expression e, String operationNa
6363
GEO_SHAPE.typeName(),
6464
CARTESIAN_SHAPE.typeName() };
6565
private static final String[] POINT_TYPE_NAMES = new String[] { GEO_POINT.typeName(), CARTESIAN_POINT.typeName() };
66-
private static final String[] NON_SPATIAL_TYPE_NAMES = DataType.types()
67-
.stream()
68-
.filter(DataType::isRepresentable)
69-
.filter(t -> DataType.isSpatial(t) == false)
70-
.map(DataType::esType)
71-
.toArray(String[]::new);
7266

7367
public static Expression.TypeResolution isSpatialPoint(Expression e, String operationName, TypeResolutions.ParamOrdinal paramOrd) {
7468
return isType(e, DataType::isSpatialPoint, operationName, paramOrd, POINT_TYPE_NAMES);
@@ -77,9 +71,4 @@ public static Expression.TypeResolution isSpatialPoint(Expression e, String oper
7771
public static Expression.TypeResolution isSpatial(Expression e, String operationName, TypeResolutions.ParamOrdinal paramOrd) {
7872
return isType(e, DataType::isSpatial, operationName, paramOrd, SPATIAL_TYPE_NAMES);
7973
}
80-
81-
public static Expression.TypeResolution isNotSpatial(Expression e, String operationName, TypeResolutions.ParamOrdinal paramOrd) {
82-
return isType(e, t -> DataType.isSpatial(t) == false, operationName, paramOrd, NON_SPATIAL_TYPE_NAMES);
83-
}
84-
8574
}

x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/aggregate/Values.java

Lines changed: 34 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -50,11 +50,28 @@ public class Values extends AggregateFunction implements ToAggregator {
5050
Map.entry(DataType.SEMANTIC_TEXT, ValuesBytesRefAggregatorFunctionSupplier::new),
5151
Map.entry(DataType.IP, ValuesBytesRefAggregatorFunctionSupplier::new),
5252
Map.entry(DataType.VERSION, ValuesBytesRefAggregatorFunctionSupplier::new),
53+
Map.entry(DataType.GEO_POINT, ValuesBytesRefAggregatorFunctionSupplier::new),
54+
Map.entry(DataType.CARTESIAN_POINT, ValuesBytesRefAggregatorFunctionSupplier::new),
55+
Map.entry(DataType.GEO_SHAPE, ValuesBytesRefAggregatorFunctionSupplier::new),
56+
Map.entry(DataType.CARTESIAN_SHAPE, ValuesBytesRefAggregatorFunctionSupplier::new),
5357
Map.entry(DataType.BOOLEAN, ValuesBooleanAggregatorFunctionSupplier::new)
5458
);
5559

5660
@FunctionInfo(
57-
returnType = { "boolean", "date", "date_nanos", "double", "integer", "ip", "keyword", "long", "version" },
61+
returnType = {
62+
"boolean",
63+
"cartesian_point",
64+
"cartesian_shape",
65+
"date",
66+
"date_nanos",
67+
"double",
68+
"geo_point",
69+
"geo_shape",
70+
"integer",
71+
"ip",
72+
"keyword",
73+
"long",
74+
"version" },
5875
preview = true,
5976
description = "Returns all values in a group as a multivalued field. The order of the returned values isn't guaranteed. "
6077
+ "If you need the values returned in order use <<esql-mv_sort>>.",
@@ -74,7 +91,21 @@ public Values(
7491
Source source,
7592
@Param(
7693
name = "field",
77-
type = { "boolean", "date", "date_nanos", "double", "integer", "ip", "keyword", "long", "text", "version" }
94+
type = {
95+
"boolean",
96+
"cartesian_point",
97+
"cartesian_shape",
98+
"date",
99+
"date_nanos",
100+
"double",
101+
"geo_point",
102+
"geo_shape",
103+
"integer",
104+
"ip",
105+
"keyword",
106+
"long",
107+
"text",
108+
"version" }
78109
) Expression v
79110
) {
80111
this(source, v, Literal.TRUE);
@@ -115,13 +146,7 @@ public DataType dataType() {
115146

116147
@Override
117148
protected TypeResolution resolveType() {
118-
return TypeResolutions.isType(
119-
field(),
120-
SUPPLIERS::containsKey,
121-
sourceText(),
122-
DEFAULT,
123-
"any type except unsigned_long and spatial types"
124-
);
149+
return TypeResolutions.isType(field(), SUPPLIERS::containsKey, sourceText(), DEFAULT, "any type except unsigned_long");
125150
}
126151

127152
@Override

x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/ValuesErrorTests.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,6 @@ protected Expression build(Source source, List<Expression> args) {
3232

3333
@Override
3434
protected Matcher<String> expectedTypeErrorMatcher(List<Set<DataType>> validPerPosition, List<DataType> signature) {
35-
return equalTo(typeErrorMessage(false, validPerPosition, signature, (v, p) -> "any type except unsigned_long and spatial types"));
35+
return equalTo(typeErrorMessage(false, validPerPosition, signature, (v, p) -> "any type except unsigned_long"));
3636
}
3737
}

x-pack/plugin/src/yamlRestTest/resources/rest-api-spec/test/esql/130_spatial.yml

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -149,19 +149,25 @@ geo_point unsortable with limit from row:
149149

150150
---
151151
values unsupported for geo_point:
152+
- requires:
153+
capabilities:
154+
- method: POST
155+
path: /_query
156+
parameters: [ method, path, parameters, capabilities ]
157+
capabilities: [ agg_values_spatial ]
158+
reason: "Spatial types added to values aggregation in 8.19.0"
159+
test_runner_features: [ capabilities, allowed_warnings_regex ]
152160
- do:
153-
catch: '/.+argument of \[VALUES\(location\)\] must be .+/'
154-
esql.query:
155-
body:
156-
query: 'FROM geo_points | STATS VALUES(location)'
157-
158-
---
159-
values unsupported for geo_point status code:
160-
- do:
161-
catch: bad_request
161+
allowed_warnings_regex:
162+
- "No limit defined, adding default limit of \\[.*\\]"
162163
esql.query:
163164
body:
164-
query: 'FROM geo_points | STATS VALUES(location)'
165+
query: 'FROM geo_points | STATS locations = VALUES(location)'
166+
- length: { columns: 1 }
167+
- match: { columns.0.name: locations }
168+
- match: { columns.0.type: geo_point }
169+
- length: { values: 1 }
170+
- match: { values.0.0: ["POINT (1.0 -1.0)", "POINT (-1.0 1.0)"] }
165171

166172
---
167173
cartesian_point:

0 commit comments

Comments
 (0)