Skip to content

Commit 04ca191

Browse files
authored
Move distance_feature query building into MFT (#60614)
This moves the `distance_feature` query building out of `DistanceFeatureQueryBuilder` and into subclasses of `MappedFieldType`. Without this we don't have a chance of supporting this for runtime fields. In general I'm not sad to see the `instanceof`s go.
1 parent ba88f0b commit 04ca191

File tree

4 files changed

+44
-31
lines changed

4 files changed

+44
-31
lines changed

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

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
import org.elasticsearch.common.time.DateFormatters;
4040
import org.elasticsearch.common.time.DateMathParser;
4141
import org.elasticsearch.common.time.DateUtils;
42+
import org.elasticsearch.common.unit.TimeValue;
4243
import org.elasticsearch.common.util.LocaleUtils;
4344
import org.elasticsearch.index.fielddata.IndexFieldData;
4445
import org.elasticsearch.index.fielddata.IndexNumericFieldData.NumericType;
@@ -91,6 +92,11 @@ public Instant clampToValidRange(Instant instant) {
9192
public long parsePointAsMillis(byte[] value) {
9293
return LongPoint.decodeDimension(value, 0);
9394
}
95+
96+
@Override
97+
protected Query distanceFeatureQuery(String field, float boost, long origin, TimeValue pivot) {
98+
return LongPoint.newDistanceFeatureQuery(field, boost, origin, pivot.getMillis());
99+
}
94100
},
95101
NANOSECONDS(DATE_NANOS_CONTENT_TYPE, NumericType.DATE_NANOSECONDS) {
96102
@Override
@@ -112,6 +118,11 @@ public Instant clampToValidRange(Instant instant) {
112118
public long parsePointAsMillis(byte[] value) {
113119
return DateUtils.toMilliSeconds(LongPoint.decodeDimension(value, 0));
114120
}
121+
122+
@Override
123+
protected Query distanceFeatureQuery(String field, float boost, long origin, TimeValue pivot) {
124+
return LongPoint.newDistanceFeatureQuery(field, boost, origin, pivot.getNanos());
125+
}
115126
};
116127

117128
private final String type;
@@ -159,6 +170,8 @@ public static Resolution ofOrdinal(int ord) {
159170
}
160171
throw new IllegalArgumentException("unknown resolution ordinal [" + ord + "]");
161172
}
173+
174+
protected abstract Query distanceFeatureQuery(String field, float boost, long origin, TimeValue pivot);
162175
}
163176

164177
private static DateFieldMapper toType(FieldMapper in) {
@@ -359,6 +372,13 @@ public long parseToLong(Object value, boolean roundUp,
359372
return resolution.convert(instant);
360373
}
361374

375+
@Override
376+
public Query distanceFeatureQuery(Object origin, String pivot, float boost, QueryShardContext context) {
377+
long originLong = parseToLong(origin, true, null, null, context::nowInMillis);
378+
TimeValue pivotTime = TimeValue.parseTimeValue(pivot, "distance_feature.pivot");
379+
return resolution.distanceFeatureQuery(name(), boost, originLong, pivotTime);
380+
}
381+
362382
@Override
363383
public Relation isFieldWithinQuery(IndexReader reader,
364384
Object from, Object to, boolean includeLower, boolean includeUpper,

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

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,18 @@
2424
import org.apache.lucene.document.StoredField;
2525
import org.apache.lucene.index.IndexOptions;
2626
import org.apache.lucene.index.IndexableField;
27+
import org.apache.lucene.search.Query;
2728
import org.elasticsearch.ElasticsearchParseException;
2829
import org.elasticsearch.common.Explicit;
2930
import org.elasticsearch.common.geo.GeoPoint;
3031
import org.elasticsearch.common.geo.GeoUtils;
32+
import org.elasticsearch.common.unit.DistanceUnit;
3133
import org.elasticsearch.common.xcontent.XContentParser;
3234
import org.elasticsearch.geometry.Point;
3335
import org.elasticsearch.index.fielddata.IndexFieldData;
3436
import org.elasticsearch.index.fielddata.plain.AbstractLatLonPointIndexFieldData;
3537
import org.elasticsearch.index.mapper.GeoPointFieldMapper.ParsedGeoPoint;
38+
import org.elasticsearch.index.query.QueryShardContext;
3639
import org.elasticsearch.index.query.VectorGeoPointShapeQueryProcessor;
3740
import org.elasticsearch.search.aggregations.support.CoreValuesSourceType;
3841

@@ -186,6 +189,20 @@ public IndexFieldData.Builder fielddataBuilder(String fullyQualifiedIndexName) {
186189
return new AbstractLatLonPointIndexFieldData.Builder(name(), CoreValuesSourceType.GEOPOINT);
187190
}
188191

192+
@Override
193+
public Query distanceFeatureQuery(Object origin, String pivot, float boost, QueryShardContext context) {
194+
GeoPoint originGeoPoint;
195+
if (origin instanceof GeoPoint) {
196+
originGeoPoint = (GeoPoint) origin;
197+
} else if (origin instanceof String) {
198+
originGeoPoint = GeoUtils.parseFromString((String) origin);
199+
} else {
200+
throw new IllegalArgumentException("Illegal type ["+ origin.getClass() + "] for [origin]! " +
201+
"Must be of type [geo_point] or [string] for geo_point fields!");
202+
}
203+
double pivotDouble = DistanceUnit.DEFAULT.parse(pivot, DistanceUnit.DEFAULT);
204+
return LatLonPoint.newDistanceFeatureQuery(name(), boost, originGeoPoint.lat(), originGeoPoint.lon(), pivotDouble);
205+
}
189206
}
190207

191208
// Eclipse requires the AbstractPointGeometryFieldMapper prefix or it can't find ParsedPoint

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
import org.elasticsearch.common.unit.Fuzziness;
4444
import org.elasticsearch.index.analysis.NamedAnalyzer;
4545
import org.elasticsearch.index.fielddata.IndexFieldData;
46+
import org.elasticsearch.index.query.DistanceFeatureQueryBuilder;
4647
import org.elasticsearch.index.query.QueryRewriteContext;
4748
import org.elasticsearch.index.query.QueryShardContext;
4849
import org.elasticsearch.index.query.QueryShardException;
@@ -241,6 +242,11 @@ public SpanQuery spanPrefixQuery(String value, SpanMultiTermQueryWrapper.SpanRew
241242
+ "] which is of type [" + typeName() + "]");
242243
}
243244

245+
public Query distanceFeatureQuery(Object origin, String pivot, float boost, QueryShardContext context) {
246+
throw new IllegalArgumentException("Illegal data type of [" + typeName() + "]!"+
247+
"[" + DistanceFeatureQueryBuilder.NAME + "] query can only be run on a date, date_nanos or geo_point field type!");
248+
}
249+
244250
/**
245251
* Create an {@link IntervalsSource} to be used for proximity queries
246252
*/

server/src/main/java/org/elasticsearch/index/query/DistanceFeatureQueryBuilder.java

Lines changed: 1 addition & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,6 @@
1919

2020
package org.elasticsearch.index.query;
2121

22-
import org.apache.lucene.document.LatLonPoint;
23-
import org.apache.lucene.document.LongPoint;
2422
import org.apache.lucene.search.Query;
2523
import org.elasticsearch.common.ParseField;
2624
import org.elasticsearch.common.ParsingException;
@@ -29,15 +27,10 @@
2927
import org.elasticsearch.common.io.stream.StreamInput;
3028
import org.elasticsearch.common.io.stream.StreamOutput;
3129
import org.elasticsearch.common.lucene.search.Queries;
32-
import org.elasticsearch.common.unit.DistanceUnit;
33-
import org.elasticsearch.common.unit.TimeValue;
3430
import org.elasticsearch.common.xcontent.ConstructingObjectParser;
3531
import org.elasticsearch.common.xcontent.ObjectParser;
3632
import org.elasticsearch.common.xcontent.XContentBuilder;
3733
import org.elasticsearch.common.xcontent.XContentParser;
38-
import org.elasticsearch.index.mapper.DateFieldMapper;
39-
import org.elasticsearch.index.mapper.DateFieldMapper.DateFieldType;
40-
import org.elasticsearch.index.mapper.GeoPointFieldMapper.GeoPointFieldType;
4134
import org.elasticsearch.index.mapper.MappedFieldType;
4235

4336
import java.io.IOException;
@@ -119,30 +112,7 @@ protected Query doToQuery(QueryShardContext context) throws IOException {
119112
if (fieldType == null) {
120113
return Queries.newMatchNoDocsQuery("Can't run [" + NAME + "] query on unmapped fields!");
121114
}
122-
Object originObj = origin.origin();
123-
if (fieldType instanceof DateFieldType) {
124-
long originLong = ((DateFieldType) fieldType).parseToLong(originObj, true, null, null, context::nowInMillis);
125-
TimeValue pivotVal = TimeValue.parseTimeValue(pivot, DistanceFeatureQueryBuilder.class.getSimpleName() + ".pivot");
126-
if (((DateFieldType) fieldType).resolution() == DateFieldMapper.Resolution.MILLISECONDS) {
127-
return LongPoint.newDistanceFeatureQuery(field, boost, originLong, pivotVal.getMillis());
128-
} else { // NANOSECONDS
129-
return LongPoint.newDistanceFeatureQuery(field, boost, originLong, pivotVal.getNanos());
130-
}
131-
} else if (fieldType instanceof GeoPointFieldType) {
132-
GeoPoint originGeoPoint;
133-
if (originObj instanceof GeoPoint) {
134-
originGeoPoint = (GeoPoint) originObj;
135-
} else if (originObj instanceof String) {
136-
originGeoPoint = GeoUtils.parseFromString((String) originObj);
137-
} else {
138-
throw new IllegalArgumentException("Illegal type ["+ origin.getClass() + "] for [origin]! " +
139-
"Must be of type [geo_point] or [string] for geo_point fields!");
140-
}
141-
double pivotDouble = DistanceUnit.DEFAULT.parse(pivot, DistanceUnit.DEFAULT);
142-
return LatLonPoint.newDistanceFeatureQuery(field, boost, originGeoPoint.lat(), originGeoPoint.lon(), pivotDouble);
143-
}
144-
throw new IllegalArgumentException("Illegal data type of [" + fieldType.typeName() + "]!"+
145-
"[" + NAME + "] query can only be run on a date, date_nanos or geo_point field type!");
115+
return fieldType.distanceFeatureQuery(origin.origin(), pivot, boost, context);
146116
}
147117

148118
String fieldName() {

0 commit comments

Comments
 (0)