From fb83508654fbfd478928b69195c7999e8a4265c9 Mon Sep 17 00:00:00 2001 From: iverase Date: Fri, 9 Jul 2021 12:17:49 +0200 Subject: [PATCH 1/6] Geometry formatters should be applied to the full array --- .../action/PainlessExecuteAction.java | 8 ++--- .../common/geo/GeoFormatterFactory.java | 20 +++++++++--- .../mapper/AbstractGeometryFieldMapper.java | 18 +++++++---- .../index/mapper/GeoPointFieldMapper.java | 14 +++++--- .../index/mapper/GeoShapeFieldMapper.java | 2 +- .../index/mapper/GeoShapeParser.java | 5 +++ .../mapper/LegacyGeoShapeFieldMapper.java | 10 ++++-- .../search/lookup/FieldValues.java | 32 +++++++++++++++++++ .../common/CartesianFormatterFactory.java | 20 +++++++++--- .../GeoShapeWithDocValuesFieldMapper.java | 2 +- .../index/mapper/PointFieldMapper.java | 10 ++++-- .../index/mapper/ShapeFieldMapper.java | 2 +- 12 files changed, 108 insertions(+), 35 deletions(-) diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/action/PainlessExecuteAction.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/action/PainlessExecuteAction.java index 491974ccc873f..194f9a0666b6d 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/action/PainlessExecuteAction.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/action/PainlessExecuteAction.java @@ -588,12 +588,12 @@ static Response innerShardOperation(Request request, ScriptService scriptService List points = new ArrayList<>(); geoPointFieldScript.runGeoPointForDoc(0, gp -> points.add(new GeoPoint(gp))); // convert geo points to the standard format of the fields api - Function format = GeoFormatterFactory.getFormatter(GeoFormatterFactory.GEOJSON); - List objects = new ArrayList<>(); + Function, List> format = GeoFormatterFactory.getFormatter(GeoFormatterFactory.GEOJSON); + List geometries = new ArrayList<>(); for (GeoPoint gp : points) { - objects.add(format.apply(new Point(gp.getLon(), gp.getLat()))); + geometries.add(new Point(gp.getLon(), gp.getLat())); } - return new Response(objects); + return new Response(format.apply(geometries)); }, indexService); } else if (scriptContext == IpFieldScript.CONTEXT) { return prepareRamIndex(request, (context, leafReaderContext) -> { diff --git a/server/src/main/java/org/elasticsearch/common/geo/GeoFormatterFactory.java b/server/src/main/java/org/elasticsearch/common/geo/GeoFormatterFactory.java index ab64b92859580..9ea034936c9fa 100644 --- a/server/src/main/java/org/elasticsearch/common/geo/GeoFormatterFactory.java +++ b/server/src/main/java/org/elasticsearch/common/geo/GeoFormatterFactory.java @@ -11,7 +11,9 @@ import org.elasticsearch.geometry.Geometry; import org.elasticsearch.geometry.utils.WellKnownText; +import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.function.Function; @@ -23,17 +25,25 @@ public class GeoFormatterFactory { public static final String GEOJSON = "geojson"; public static final String WKT = "wkt"; - private static final Map> FORMATTERS = new HashMap<>(); + private static final Map, List>> FORMATTERS = new HashMap<>(); static { - FORMATTERS.put(GEOJSON, GeoJson::toMap); - FORMATTERS.put(WKT, WellKnownText::toWKT); + FORMATTERS.put(GEOJSON, geometries -> { + final List objects = new ArrayList<>(geometries.size()); + geometries.forEach((geometry) -> objects.add(GeoJson.toMap(geometry))); + return objects; + }); + FORMATTERS.put(WKT, geometries -> { + final List objects = new ArrayList<>(geometries.size()); + geometries.forEach((geometry) -> objects.add(WellKnownText.toWKT(geometry))); + return objects; + }); } /** * Returns a formatter by name */ - public static Function getFormatter(String name) { - Function format = FORMATTERS.get(name); + public static Function, List> getFormatter(String name) { + Function, List> format = FORMATTERS.get(name); if (format == null) { throw new IllegalArgumentException("Unrecognized geometry format [" + name + "]."); } diff --git a/server/src/main/java/org/elasticsearch/index/mapper/AbstractGeometryFieldMapper.java b/server/src/main/java/org/elasticsearch/index/mapper/AbstractGeometryFieldMapper.java index 0742c2a234082..c6cd197a98b8a 100644 --- a/server/src/main/java/org/elasticsearch/index/mapper/AbstractGeometryFieldMapper.java +++ b/server/src/main/java/org/elasticsearch/index/mapper/AbstractGeometryFieldMapper.java @@ -13,6 +13,7 @@ import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.common.xcontent.support.MapXContentParser; import org.elasticsearch.core.CheckedConsumer; +import org.elasticsearch.geometry.Geometry; import org.elasticsearch.index.analysis.NamedAnalyzer; import org.elasticsearch.index.query.SearchExecutionContext; @@ -52,13 +53,16 @@ public abstract void parse( CheckedConsumer consumer, Consumer onMalformed) throws IOException; - private void fetchFromSource(Object sourceMap, Consumer consumer, Function formatter) { + protected abstract Geometry toGeometry(T shape); + + private void fetchFromSource(Object sourceMap, Consumer consumer) { try (XContentParser parser = MapXContentParser.wrapObject(sourceMap)) { - parse(parser, v -> consumer.accept(formatter.apply(v)), e -> {}); /* ignore malformed */ + parse(parser, v -> consumer.accept(toGeometry(v)), e -> {}); /* ignore malformed */ } catch (IOException e) { throw new UncheckedIOException(e); } } + } public abstract static class AbstractGeometryFieldType extends MappedFieldType { @@ -80,17 +84,17 @@ public final Query termQuery(Object value, SearchExecutionContext context) { /** * Gets the formatter by name. */ - protected abstract Function getFormatter(String format); + protected abstract Function, List> getFormatter(String format); @Override public ValueFetcher valueFetcher(SearchExecutionContext context, String format) { - Function formatter = getFormatter(format != null ? format : GeoFormatterFactory.GEOJSON); + Function, List> formatter = getFormatter(format != null ? format : GeoFormatterFactory.GEOJSON); return new ArraySourceValueFetcher(name(), context) { @Override protected Object parseSourceValue(Object value) { - List values = new ArrayList<>(); - geometryParser.fetchFromSource(value, values::add, formatter); - return values; + final List values = new ArrayList<>(); + geometryParser.fetchFromSource(value, values::add); + return formatter.apply(values); } }; } diff --git a/server/src/main/java/org/elasticsearch/index/mapper/GeoPointFieldMapper.java b/server/src/main/java/org/elasticsearch/index/mapper/GeoPointFieldMapper.java index eae0dcf7efad1..728bc4998ec1c 100644 --- a/server/src/main/java/org/elasticsearch/index/mapper/GeoPointFieldMapper.java +++ b/server/src/main/java/org/elasticsearch/index/mapper/GeoPointFieldMapper.java @@ -240,9 +240,8 @@ public String typeName() { } @Override - protected Function getFormatter(String format) { - Function formatter = GeoFormatterFactory.getFormatter(format); - return (point) -> formatter.apply(new Point(point.lon(), point.lat())); + protected Function, List> getFormatter(String format) { + return GeoFormatterFactory.getFormatter(format); } @Override @@ -250,8 +249,8 @@ public ValueFetcher valueFetcher(SearchExecutionContext context, String format) if (scriptValues == null) { return super.valueFetcher(context, format); } - Function formatter = getFormatter(format != null ? format : GeoFormatterFactory.GEOJSON); - return FieldValues.valueFetcher(scriptValues, v -> formatter.apply((GeoPoint) v), context); + Function, List> formatter = getFormatter(format != null ? format : GeoFormatterFactory.GEOJSON); + return FieldValues.valueFetcher(scriptValues, formatter, context, geometryParser::toGeometry); } @Override @@ -321,6 +320,11 @@ protected GeoPoint validate(GeoPoint in) { return in; } + @Override + protected Geometry toGeometry(GeoPoint point) { + return new Point(point.lon(), point.lat()); + } + private boolean isNormalizable(double coord) { return Double.isNaN(coord) == false && Double.isInfinite(coord) == false; } diff --git a/server/src/main/java/org/elasticsearch/index/mapper/GeoShapeFieldMapper.java b/server/src/main/java/org/elasticsearch/index/mapper/GeoShapeFieldMapper.java index 5e10c8ed8d4b1..2657ac4285663 100644 --- a/server/src/main/java/org/elasticsearch/index/mapper/GeoShapeFieldMapper.java +++ b/server/src/main/java/org/elasticsearch/index/mapper/GeoShapeFieldMapper.java @@ -141,7 +141,7 @@ public Query geoShapeQuery(Geometry shape, String fieldName, ShapeRelation relat } @Override - protected Function getFormatter(String format) { + protected Function, List> getFormatter(String format) { return GeoFormatterFactory.getFormatter(format); } } diff --git a/server/src/main/java/org/elasticsearch/index/mapper/GeoShapeParser.java b/server/src/main/java/org/elasticsearch/index/mapper/GeoShapeParser.java index d9d5ef152d9af..36b57badf92fe 100644 --- a/server/src/main/java/org/elasticsearch/index/mapper/GeoShapeParser.java +++ b/server/src/main/java/org/elasticsearch/index/mapper/GeoShapeParser.java @@ -43,4 +43,9 @@ public void parse( onMalformed.accept(e); } } + + @Override + protected Geometry toGeometry(Geometry geometry) { + return geometry; + } } diff --git a/server/src/main/java/org/elasticsearch/index/mapper/LegacyGeoShapeFieldMapper.java b/server/src/main/java/org/elasticsearch/index/mapper/LegacyGeoShapeFieldMapper.java index de49983071ccf..1d92d884405e4 100644 --- a/server/src/main/java/org/elasticsearch/index/mapper/LegacyGeoShapeFieldMapper.java +++ b/server/src/main/java/org/elasticsearch/index/mapper/LegacyGeoShapeFieldMapper.java @@ -336,6 +336,11 @@ public void parse( onMalformed.accept(e); } } + + @Override + protected Geometry toGeometry(ShapeBuilder shapeBuilder) { + return shapeBuilder.buildGeometry(); + } } public static final class GeoShapeFieldType extends AbstractShapeGeometryFieldType> implements GeoShapeQueryable { @@ -454,9 +459,8 @@ public PrefixTreeStrategy resolvePrefixTreeStrategy(String strategyName) { } @Override - protected Function, Object> getFormatter(String format) { - Function formatter = GeoFormatterFactory.getFormatter(format); - return (g) -> formatter.apply(g.buildGeometry()); + protected Function, List> getFormatter(String format) { + return GeoFormatterFactory.getFormatter(format); } } diff --git a/server/src/main/java/org/elasticsearch/search/lookup/FieldValues.java b/server/src/main/java/org/elasticsearch/search/lookup/FieldValues.java index c0efd774d5bd6..c4d173fb24d6f 100644 --- a/server/src/main/java/org/elasticsearch/search/lookup/FieldValues.java +++ b/server/src/main/java/org/elasticsearch/search/lookup/FieldValues.java @@ -70,4 +70,36 @@ public List fetchValues(SourceLookup lookup) { } }; } + + /** + * Creates a {@link ValueFetcher} that fetches values from a {@link FieldValues} instance + * @param fieldValues the source of the values + * @param formatter a function to format the list values + * @param context the search execution context + * @param transformer a function that transform field values into formatter values + * @return the value fetcher + */ + static ValueFetcher valueFetcher(FieldValues fieldValues, Function, List> formatter, + SearchExecutionContext context, Function transformer) { + return new ValueFetcher() { + LeafReaderContext ctx; + + @Override + public void setNextReader(LeafReaderContext context) { + this.ctx = context; + } + + @Override + public List fetchValues(SourceLookup lookup) { + List values = new ArrayList<>(); + try { + fieldValues.valuesForDoc(context.lookup(), ctx, lookup.docId(), v -> values.add(transformer.apply(v))); + } catch (Exception e) { + // ignore errors - if they exist here then they existed at index time + // and so on_script_error must have been set to `ignore` + } + return formatter.apply(values); + } + }; + } } diff --git a/x-pack/plugin/spatial/src/main/java/org/elasticsearch/xpack/spatial/common/CartesianFormatterFactory.java b/x-pack/plugin/spatial/src/main/java/org/elasticsearch/xpack/spatial/common/CartesianFormatterFactory.java index b941845b08f38..e51ec57290fe7 100644 --- a/x-pack/plugin/spatial/src/main/java/org/elasticsearch/xpack/spatial/common/CartesianFormatterFactory.java +++ b/x-pack/plugin/spatial/src/main/java/org/elasticsearch/xpack/spatial/common/CartesianFormatterFactory.java @@ -11,7 +11,9 @@ import org.elasticsearch.geometry.Geometry; import org.elasticsearch.geometry.utils.WellKnownText; +import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.function.Function; @@ -23,17 +25,25 @@ public class CartesianFormatterFactory { public static final String GEOJSON = "geojson"; public static final String WKT = "wkt"; - private static final Map> FORMATTERS = new HashMap<>(); + private static final Map, List>> FORMATTERS = new HashMap<>(); static { - FORMATTERS.put(GEOJSON, GeoJson::toMap); - FORMATTERS.put(WKT, WellKnownText::toWKT); + FORMATTERS.put(GEOJSON, geometries -> { + final List objects = new ArrayList<>(geometries.size()); + geometries.forEach((geometry) -> objects.add(GeoJson.toMap(geometry))); + return objects; + }); + FORMATTERS.put(WKT, geometries -> { + final List objects = new ArrayList<>(geometries.size()); + geometries.forEach((geometry) -> objects.add(WellKnownText.toWKT(geometry))); + return objects; + }); } /** * Returns a formatter by name */ - public static Function getFormatter(String name) { - Function format = FORMATTERS.get(name); + public static Function, List> getFormatter(String name) { + Function, List> format = FORMATTERS.get(name); if (format == null) { throw new IllegalArgumentException("Unrecognized geometry format [" + name + "]."); } diff --git a/x-pack/plugin/spatial/src/main/java/org/elasticsearch/xpack/spatial/index/mapper/GeoShapeWithDocValuesFieldMapper.java b/x-pack/plugin/spatial/src/main/java/org/elasticsearch/xpack/spatial/index/mapper/GeoShapeWithDocValuesFieldMapper.java index 2bad626c1c045..9b74d207dd356 100644 --- a/x-pack/plugin/spatial/src/main/java/org/elasticsearch/xpack/spatial/index/mapper/GeoShapeWithDocValuesFieldMapper.java +++ b/x-pack/plugin/spatial/src/main/java/org/elasticsearch/xpack/spatial/index/mapper/GeoShapeWithDocValuesFieldMapper.java @@ -173,7 +173,7 @@ public Query geoShapeQuery(Geometry shape, String fieldName, ShapeRelation relat } @Override - protected Function getFormatter(String format) { + protected Function, List> getFormatter(String format) { return GeoFormatterFactory.getFormatter(format); } } diff --git a/x-pack/plugin/spatial/src/main/java/org/elasticsearch/xpack/spatial/index/mapper/PointFieldMapper.java b/x-pack/plugin/spatial/src/main/java/org/elasticsearch/xpack/spatial/index/mapper/PointFieldMapper.java index 5164d2c5fe913..7cf72cd6ddc8a 100644 --- a/x-pack/plugin/spatial/src/main/java/org/elasticsearch/xpack/spatial/index/mapper/PointFieldMapper.java +++ b/x-pack/plugin/spatial/src/main/java/org/elasticsearch/xpack/spatial/index/mapper/PointFieldMapper.java @@ -179,9 +179,8 @@ public Query shapeQuery(Geometry shape, String fieldName, ShapeRelation relation } @Override - protected Function getFormatter(String format) { - Function formatter = CartesianFormatterFactory.getFormatter(format); - return (point) -> formatter.apply(new Point(point.getX(), point.getY())); + protected Function, List> getFormatter(String format) { + return CartesianFormatterFactory.getFormatter(format); } } @@ -210,6 +209,11 @@ protected CartesianPoint validate(CartesianPoint in) { return in; } + @Override + protected Geometry toGeometry(CartesianPoint point) { + return new Point(point.getX(), point.getY()); + } + @Override protected void reset(CartesianPoint in, double x, double y) { in.reset(x, y); diff --git a/x-pack/plugin/spatial/src/main/java/org/elasticsearch/xpack/spatial/index/mapper/ShapeFieldMapper.java b/x-pack/plugin/spatial/src/main/java/org/elasticsearch/xpack/spatial/index/mapper/ShapeFieldMapper.java index 360f960932885..90ff74665011f 100644 --- a/x-pack/plugin/spatial/src/main/java/org/elasticsearch/xpack/spatial/index/mapper/ShapeFieldMapper.java +++ b/x-pack/plugin/spatial/src/main/java/org/elasticsearch/xpack/spatial/index/mapper/ShapeFieldMapper.java @@ -124,7 +124,7 @@ public String typeName() { } @Override - protected Function getFormatter(String format) { + protected Function, List> getFormatter(String format) { return CartesianFormatterFactory.getFormatter(format); } } From 3aa7fe84f859376cdbac13fd2865579bd339f745 Mon Sep 17 00:00:00 2001 From: iverase Date: Fri, 9 Jul 2021 12:25:34 +0200 Subject: [PATCH 2/6] javadoc --- .../index/mapper/AbstractGeometryFieldMapper.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/server/src/main/java/org/elasticsearch/index/mapper/AbstractGeometryFieldMapper.java b/server/src/main/java/org/elasticsearch/index/mapper/AbstractGeometryFieldMapper.java index c6cd197a98b8a..bcf08b7a8456f 100644 --- a/server/src/main/java/org/elasticsearch/index/mapper/AbstractGeometryFieldMapper.java +++ b/server/src/main/java/org/elasticsearch/index/mapper/AbstractGeometryFieldMapper.java @@ -53,6 +53,9 @@ public abstract void parse( CheckedConsumer consumer, Consumer onMalformed) throws IOException; + /** + * Translate the given {@link T} into a {@link Geometry}. + */ protected abstract Geometry toGeometry(T shape); private void fetchFromSource(Object sourceMap, Consumer consumer) { From 7669374f2fee383f1327cf89bfd1b37e7f31773c Mon Sep 17 00:00:00 2001 From: iverase Date: Fri, 9 Jul 2021 12:29:43 +0200 Subject: [PATCH 3/6] extra space --- .../org/elasticsearch/index/mapper/GeoShapeFieldMapper.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/src/main/java/org/elasticsearch/index/mapper/GeoShapeFieldMapper.java b/server/src/main/java/org/elasticsearch/index/mapper/GeoShapeFieldMapper.java index 2657ac4285663..e2ca63b243392 100644 --- a/server/src/main/java/org/elasticsearch/index/mapper/GeoShapeFieldMapper.java +++ b/server/src/main/java/org/elasticsearch/index/mapper/GeoShapeFieldMapper.java @@ -141,7 +141,7 @@ public Query geoShapeQuery(Geometry shape, String fieldName, ShapeRelation relat } @Override - protected Function, List> getFormatter(String format) { + protected Function, List> getFormatter(String format) { return GeoFormatterFactory.getFormatter(format); } } From bbb74a307dab8757055ffcc8277251263834cad9 Mon Sep 17 00:00:00 2001 From: iverase Date: Fri, 9 Jul 2021 12:30:31 +0200 Subject: [PATCH 4/6] extra space --- .../spatial/index/mapper/GeoShapeWithDocValuesFieldMapper.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugin/spatial/src/main/java/org/elasticsearch/xpack/spatial/index/mapper/GeoShapeWithDocValuesFieldMapper.java b/x-pack/plugin/spatial/src/main/java/org/elasticsearch/xpack/spatial/index/mapper/GeoShapeWithDocValuesFieldMapper.java index 9b74d207dd356..94eb18e2378da 100644 --- a/x-pack/plugin/spatial/src/main/java/org/elasticsearch/xpack/spatial/index/mapper/GeoShapeWithDocValuesFieldMapper.java +++ b/x-pack/plugin/spatial/src/main/java/org/elasticsearch/xpack/spatial/index/mapper/GeoShapeWithDocValuesFieldMapper.java @@ -173,7 +173,7 @@ public Query geoShapeQuery(Geometry shape, String fieldName, ShapeRelation relat } @Override - protected Function, List> getFormatter(String format) { + protected Function, List> getFormatter(String format) { return GeoFormatterFactory.getFormatter(format); } } From 5a2d16a640f4eccf8774a1c28dad9c04a5f72291 Mon Sep 17 00:00:00 2001 From: iverase Date: Fri, 9 Jul 2021 12:32:57 +0200 Subject: [PATCH 5/6] extra space --- .../elasticsearch/index/mapper/LegacyGeoShapeFieldMapper.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/src/main/java/org/elasticsearch/index/mapper/LegacyGeoShapeFieldMapper.java b/server/src/main/java/org/elasticsearch/index/mapper/LegacyGeoShapeFieldMapper.java index 1d92d884405e4..d79d6c2b00204 100644 --- a/server/src/main/java/org/elasticsearch/index/mapper/LegacyGeoShapeFieldMapper.java +++ b/server/src/main/java/org/elasticsearch/index/mapper/LegacyGeoShapeFieldMapper.java @@ -459,7 +459,7 @@ public PrefixTreeStrategy resolvePrefixTreeStrategy(String strategyName) { } @Override - protected Function, List> getFormatter(String format) { + protected Function, List> getFormatter(String format) { return GeoFormatterFactory.getFormatter(format); } } From d75d94b0764d11aa0e7252d9445fd272db4b486f Mon Sep 17 00:00:00 2001 From: iverase Date: Wed, 14 Jul 2021 08:34:18 +0200 Subject: [PATCH 6/6] Simplify implementation --- .../action/PainlessExecuteAction.java | 12 ++--- .../common/geo/GeoFormatterFactory.java | 52 ------------------- .../common/geo/GeometryFormatterFactory.java | 46 ++++++++++++++++ .../mapper/AbstractGeometryFieldMapper.java | 18 +++---- .../index/mapper/GeoPointFieldMapper.java | 15 ++---- .../index/mapper/GeoShapeFieldMapper.java | 4 +- .../index/mapper/GeoShapeParser.java | 5 -- .../mapper/LegacyGeoShapeFieldMapper.java | 11 ++-- .../search/lookup/FieldValues.java | 7 ++- .../common/CartesianFormatterFactory.java | 52 ------------------- .../GeoShapeWithDocValuesFieldMapper.java | 4 +- .../index/mapper/PointFieldMapper.java | 11 ++-- .../index/mapper/ShapeFieldMapper.java | 4 +- 13 files changed, 76 insertions(+), 165 deletions(-) delete mode 100644 server/src/main/java/org/elasticsearch/common/geo/GeoFormatterFactory.java create mode 100644 server/src/main/java/org/elasticsearch/common/geo/GeometryFormatterFactory.java delete mode 100644 x-pack/plugin/spatial/src/main/java/org/elasticsearch/xpack/spatial/common/CartesianFormatterFactory.java diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/action/PainlessExecuteAction.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/action/PainlessExecuteAction.java index 194f9a0666b6d..e3d6baf15f94b 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/action/PainlessExecuteAction.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/action/PainlessExecuteAction.java @@ -34,9 +34,9 @@ import org.elasticsearch.cluster.routing.ShardsIterator; import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.CheckedBiFunction; +import org.elasticsearch.common.geo.GeometryFormatterFactory; import org.elasticsearch.common.xcontent.ParseField; import org.elasticsearch.common.bytes.BytesReference; -import org.elasticsearch.common.geo.GeoFormatterFactory; import org.elasticsearch.common.geo.GeoPoint; import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.io.stream.StreamInput; @@ -51,7 +51,6 @@ import org.elasticsearch.common.xcontent.XContentHelper; import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.common.xcontent.XContentType; -import org.elasticsearch.geometry.Geometry; import org.elasticsearch.geometry.Point; import org.elasticsearch.index.Index; import org.elasticsearch.index.IndexService; @@ -588,12 +587,9 @@ static Response innerShardOperation(Request request, ScriptService scriptService List points = new ArrayList<>(); geoPointFieldScript.runGeoPointForDoc(0, gp -> points.add(new GeoPoint(gp))); // convert geo points to the standard format of the fields api - Function, List> format = GeoFormatterFactory.getFormatter(GeoFormatterFactory.GEOJSON); - List geometries = new ArrayList<>(); - for (GeoPoint gp : points) { - geometries.add(new Point(gp.getLon(), gp.getLat())); - } - return new Response(format.apply(geometries)); + Function, List> format = + GeometryFormatterFactory.getFormatter(GeometryFormatterFactory.GEOJSON, p -> new Point(p.lon(), p.lat())); + return new Response(format.apply(points)); }, indexService); } else if (scriptContext == IpFieldScript.CONTEXT) { return prepareRamIndex(request, (context, leafReaderContext) -> { diff --git a/server/src/main/java/org/elasticsearch/common/geo/GeoFormatterFactory.java b/server/src/main/java/org/elasticsearch/common/geo/GeoFormatterFactory.java deleted file mode 100644 index 9ea034936c9fa..0000000000000 --- a/server/src/main/java/org/elasticsearch/common/geo/GeoFormatterFactory.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * 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 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 or the Server - * Side Public License, v 1. - */ - -package org.elasticsearch.common.geo; - -import org.elasticsearch.geometry.Geometry; -import org.elasticsearch.geometry.utils.WellKnownText; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.function.Function; - -/** - * Output formatters supported by geo fields. - */ -public class GeoFormatterFactory { - - public static final String GEOJSON = "geojson"; - public static final String WKT = "wkt"; - - private static final Map, List>> FORMATTERS = new HashMap<>(); - static { - FORMATTERS.put(GEOJSON, geometries -> { - final List objects = new ArrayList<>(geometries.size()); - geometries.forEach((geometry) -> objects.add(GeoJson.toMap(geometry))); - return objects; - }); - FORMATTERS.put(WKT, geometries -> { - final List objects = new ArrayList<>(geometries.size()); - geometries.forEach((geometry) -> objects.add(WellKnownText.toWKT(geometry))); - return objects; - }); - } - - /** - * Returns a formatter by name - */ - public static Function, List> getFormatter(String name) { - Function, List> format = FORMATTERS.get(name); - if (format == null) { - throw new IllegalArgumentException("Unrecognized geometry format [" + name + "]."); - } - return format; - } -} diff --git a/server/src/main/java/org/elasticsearch/common/geo/GeometryFormatterFactory.java b/server/src/main/java/org/elasticsearch/common/geo/GeometryFormatterFactory.java new file mode 100644 index 0000000000000..21785bf549f0a --- /dev/null +++ b/server/src/main/java/org/elasticsearch/common/geo/GeometryFormatterFactory.java @@ -0,0 +1,46 @@ +/* + * 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 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 or the Server + * Side Public License, v 1. + */ + +package org.elasticsearch.common.geo; + +import org.elasticsearch.geometry.Geometry; +import org.elasticsearch.geometry.utils.WellKnownText; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Function; + +/** + * Output formatters supported by geometry fields. + */ +public class GeometryFormatterFactory { + + public static final String GEOJSON = "geojson"; + public static final String WKT = "wkt"; + + /** + * Returns a formatter by name + */ + public static Function, List> getFormatter(String name, Function toGeometry) { + switch (name) { + case GEOJSON: + return geometries -> { + final List objects = new ArrayList<>(geometries.size()); + geometries.forEach((shape) -> objects.add(GeoJson.toMap(toGeometry.apply(shape)))); + return objects; + }; + case WKT: + return geometries -> { + final List objects = new ArrayList<>(geometries.size()); + geometries.forEach((shape) -> objects.add(WellKnownText.toWKT(toGeometry.apply(shape)))); + return objects; + }; + default: throw new IllegalArgumentException("Unrecognized geometry format [" + name + "]."); + } + } +} diff --git a/server/src/main/java/org/elasticsearch/index/mapper/AbstractGeometryFieldMapper.java b/server/src/main/java/org/elasticsearch/index/mapper/AbstractGeometryFieldMapper.java index bcf08b7a8456f..0a6d70bf7536e 100644 --- a/server/src/main/java/org/elasticsearch/index/mapper/AbstractGeometryFieldMapper.java +++ b/server/src/main/java/org/elasticsearch/index/mapper/AbstractGeometryFieldMapper.java @@ -9,11 +9,10 @@ import org.apache.lucene.search.Query; import org.elasticsearch.common.Explicit; -import org.elasticsearch.common.geo.GeoFormatterFactory; +import org.elasticsearch.common.geo.GeometryFormatterFactory; import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.common.xcontent.support.MapXContentParser; import org.elasticsearch.core.CheckedConsumer; -import org.elasticsearch.geometry.Geometry; import org.elasticsearch.index.analysis.NamedAnalyzer; import org.elasticsearch.index.query.SearchExecutionContext; @@ -53,14 +52,9 @@ public abstract void parse( CheckedConsumer consumer, Consumer onMalformed) throws IOException; - /** - * Translate the given {@link T} into a {@link Geometry}. - */ - protected abstract Geometry toGeometry(T shape); - - private void fetchFromSource(Object sourceMap, Consumer consumer) { + private void fetchFromSource(Object sourceMap, Consumer consumer) { try (XContentParser parser = MapXContentParser.wrapObject(sourceMap)) { - parse(parser, v -> consumer.accept(toGeometry(v)), e -> {}); /* ignore malformed */ + parse(parser, v -> consumer.accept(v), e -> {}); /* ignore malformed */ } catch (IOException e) { throw new UncheckedIOException(e); } @@ -87,15 +81,15 @@ public final Query termQuery(Object value, SearchExecutionContext context) { /** * Gets the formatter by name. */ - protected abstract Function, List> getFormatter(String format); + protected abstract Function, List> getFormatter(String format); @Override public ValueFetcher valueFetcher(SearchExecutionContext context, String format) { - Function, List> formatter = getFormatter(format != null ? format : GeoFormatterFactory.GEOJSON); + Function, List> formatter = getFormatter(format != null ? format : GeometryFormatterFactory.GEOJSON); return new ArraySourceValueFetcher(name(), context) { @Override protected Object parseSourceValue(Object value) { - final List values = new ArrayList<>(); + final List values = new ArrayList<>(); geometryParser.fetchFromSource(value, values::add); return formatter.apply(values); } diff --git a/server/src/main/java/org/elasticsearch/index/mapper/GeoPointFieldMapper.java b/server/src/main/java/org/elasticsearch/index/mapper/GeoPointFieldMapper.java index 728bc4998ec1c..a2cd6b0a3eee0 100644 --- a/server/src/main/java/org/elasticsearch/index/mapper/GeoPointFieldMapper.java +++ b/server/src/main/java/org/elasticsearch/index/mapper/GeoPointFieldMapper.java @@ -18,10 +18,10 @@ import org.elasticsearch.ElasticsearchParseException; import org.elasticsearch.common.CheckedBiFunction; import org.elasticsearch.common.Explicit; -import org.elasticsearch.common.geo.GeoFormatterFactory; import org.elasticsearch.common.geo.GeoPoint; import org.elasticsearch.common.geo.GeoShapeUtils; import org.elasticsearch.common.geo.GeoUtils; +import org.elasticsearch.common.geo.GeometryFormatterFactory; import org.elasticsearch.common.geo.ShapeRelation; import org.elasticsearch.common.unit.DistanceUnit; import org.elasticsearch.common.xcontent.XContentParser; @@ -240,8 +240,8 @@ public String typeName() { } @Override - protected Function, List> getFormatter(String format) { - return GeoFormatterFactory.getFormatter(format); + protected Function, List> getFormatter(String format) { + return GeometryFormatterFactory.getFormatter(format, p -> new Point(p.lon(), p.lat())); } @Override @@ -249,8 +249,8 @@ public ValueFetcher valueFetcher(SearchExecutionContext context, String format) if (scriptValues == null) { return super.valueFetcher(context, format); } - Function, List> formatter = getFormatter(format != null ? format : GeoFormatterFactory.GEOJSON); - return FieldValues.valueFetcher(scriptValues, formatter, context, geometryParser::toGeometry); + Function, List> formatter = getFormatter(format != null ? format : GeometryFormatterFactory.GEOJSON); + return FieldValues.valueListFetcher(scriptValues, formatter, context); } @Override @@ -320,11 +320,6 @@ protected GeoPoint validate(GeoPoint in) { return in; } - @Override - protected Geometry toGeometry(GeoPoint point) { - return new Point(point.lon(), point.lat()); - } - private boolean isNormalizable(double coord) { return Double.isNaN(coord) == false && Double.isInfinite(coord) == false; } diff --git a/server/src/main/java/org/elasticsearch/index/mapper/GeoShapeFieldMapper.java b/server/src/main/java/org/elasticsearch/index/mapper/GeoShapeFieldMapper.java index e2ca63b243392..2e915e01fdd72 100644 --- a/server/src/main/java/org/elasticsearch/index/mapper/GeoShapeFieldMapper.java +++ b/server/src/main/java/org/elasticsearch/index/mapper/GeoShapeFieldMapper.java @@ -13,8 +13,8 @@ import org.apache.lucene.search.Query; import org.elasticsearch.Version; import org.elasticsearch.common.Explicit; -import org.elasticsearch.common.geo.GeoFormatterFactory; import org.elasticsearch.common.geo.GeoShapeUtils; +import org.elasticsearch.common.geo.GeometryFormatterFactory; import org.elasticsearch.common.geo.GeometryParser; import org.elasticsearch.common.geo.Orientation; import org.elasticsearch.common.geo.ShapeRelation; @@ -142,7 +142,7 @@ public Query geoShapeQuery(Geometry shape, String fieldName, ShapeRelation relat @Override protected Function, List> getFormatter(String format) { - return GeoFormatterFactory.getFormatter(format); + return GeometryFormatterFactory.getFormatter(format, Function.identity()); } } diff --git a/server/src/main/java/org/elasticsearch/index/mapper/GeoShapeParser.java b/server/src/main/java/org/elasticsearch/index/mapper/GeoShapeParser.java index 36b57badf92fe..d9d5ef152d9af 100644 --- a/server/src/main/java/org/elasticsearch/index/mapper/GeoShapeParser.java +++ b/server/src/main/java/org/elasticsearch/index/mapper/GeoShapeParser.java @@ -43,9 +43,4 @@ public void parse( onMalformed.accept(e); } } - - @Override - protected Geometry toGeometry(Geometry geometry) { - return geometry; - } } diff --git a/server/src/main/java/org/elasticsearch/index/mapper/LegacyGeoShapeFieldMapper.java b/server/src/main/java/org/elasticsearch/index/mapper/LegacyGeoShapeFieldMapper.java index d79d6c2b00204..08cf9308533d8 100644 --- a/server/src/main/java/org/elasticsearch/index/mapper/LegacyGeoShapeFieldMapper.java +++ b/server/src/main/java/org/elasticsearch/index/mapper/LegacyGeoShapeFieldMapper.java @@ -18,8 +18,8 @@ import org.elasticsearch.ElasticsearchParseException; import org.elasticsearch.Version; import org.elasticsearch.common.Explicit; -import org.elasticsearch.common.geo.GeoFormatterFactory; import org.elasticsearch.common.geo.GeoUtils; +import org.elasticsearch.common.geo.GeometryFormatterFactory; import org.elasticsearch.common.geo.Orientation; import org.elasticsearch.common.geo.ShapeRelation; import org.elasticsearch.common.geo.ShapesAvailability; @@ -336,11 +336,6 @@ public void parse( onMalformed.accept(e); } } - - @Override - protected Geometry toGeometry(ShapeBuilder shapeBuilder) { - return shapeBuilder.buildGeometry(); - } } public static final class GeoShapeFieldType extends AbstractShapeGeometryFieldType> implements GeoShapeQueryable { @@ -459,8 +454,8 @@ public PrefixTreeStrategy resolvePrefixTreeStrategy(String strategyName) { } @Override - protected Function, List> getFormatter(String format) { - return GeoFormatterFactory.getFormatter(format); + protected Function>, List> getFormatter(String format) { + return GeometryFormatterFactory.getFormatter(format, ShapeBuilder::buildGeometry); } } diff --git a/server/src/main/java/org/elasticsearch/search/lookup/FieldValues.java b/server/src/main/java/org/elasticsearch/search/lookup/FieldValues.java index c4d173fb24d6f..638ae5706897d 100644 --- a/server/src/main/java/org/elasticsearch/search/lookup/FieldValues.java +++ b/server/src/main/java/org/elasticsearch/search/lookup/FieldValues.java @@ -76,11 +76,10 @@ public List fetchValues(SourceLookup lookup) { * @param fieldValues the source of the values * @param formatter a function to format the list values * @param context the search execution context - * @param transformer a function that transform field values into formatter values * @return the value fetcher */ - static ValueFetcher valueFetcher(FieldValues fieldValues, Function, List> formatter, - SearchExecutionContext context, Function transformer) { + static ValueFetcher valueListFetcher(FieldValues fieldValues, Function, List> formatter, + SearchExecutionContext context) { return new ValueFetcher() { LeafReaderContext ctx; @@ -93,7 +92,7 @@ public void setNextReader(LeafReaderContext context) { public List fetchValues(SourceLookup lookup) { List values = new ArrayList<>(); try { - fieldValues.valuesForDoc(context.lookup(), ctx, lookup.docId(), v -> values.add(transformer.apply(v))); + fieldValues.valuesForDoc(context.lookup(), ctx, lookup.docId(), v -> values.add(v)); } catch (Exception e) { // ignore errors - if they exist here then they existed at index time // and so on_script_error must have been set to `ignore` diff --git a/x-pack/plugin/spatial/src/main/java/org/elasticsearch/xpack/spatial/common/CartesianFormatterFactory.java b/x-pack/plugin/spatial/src/main/java/org/elasticsearch/xpack/spatial/common/CartesianFormatterFactory.java deleted file mode 100644 index e51ec57290fe7..0000000000000 --- a/x-pack/plugin/spatial/src/main/java/org/elasticsearch/xpack/spatial/common/CartesianFormatterFactory.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * 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; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -package org.elasticsearch.xpack.spatial.common; - -import org.elasticsearch.common.geo.GeoJson; -import org.elasticsearch.geometry.Geometry; -import org.elasticsearch.geometry.utils.WellKnownText; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.function.Function; - -/** - * Output formatters supported by cartesian fields. - */ -public class CartesianFormatterFactory { - - public static final String GEOJSON = "geojson"; - public static final String WKT = "wkt"; - - private static final Map, List>> FORMATTERS = new HashMap<>(); - static { - FORMATTERS.put(GEOJSON, geometries -> { - final List objects = new ArrayList<>(geometries.size()); - geometries.forEach((geometry) -> objects.add(GeoJson.toMap(geometry))); - return objects; - }); - FORMATTERS.put(WKT, geometries -> { - final List objects = new ArrayList<>(geometries.size()); - geometries.forEach((geometry) -> objects.add(WellKnownText.toWKT(geometry))); - return objects; - }); - } - - /** - * Returns a formatter by name - */ - public static Function, List> getFormatter(String name) { - Function, List> format = FORMATTERS.get(name); - if (format == null) { - throw new IllegalArgumentException("Unrecognized geometry format [" + name + "]."); - } - return format; - } -} diff --git a/x-pack/plugin/spatial/src/main/java/org/elasticsearch/xpack/spatial/index/mapper/GeoShapeWithDocValuesFieldMapper.java b/x-pack/plugin/spatial/src/main/java/org/elasticsearch/xpack/spatial/index/mapper/GeoShapeWithDocValuesFieldMapper.java index 94eb18e2378da..f1cb70725f53d 100644 --- a/x-pack/plugin/spatial/src/main/java/org/elasticsearch/xpack/spatial/index/mapper/GeoShapeWithDocValuesFieldMapper.java +++ b/x-pack/plugin/spatial/src/main/java/org/elasticsearch/xpack/spatial/index/mapper/GeoShapeWithDocValuesFieldMapper.java @@ -15,8 +15,8 @@ import org.apache.lucene.search.Query; import org.elasticsearch.Version; import org.elasticsearch.common.Explicit; -import org.elasticsearch.common.geo.GeoFormatterFactory; import org.elasticsearch.common.geo.GeoShapeUtils; +import org.elasticsearch.common.geo.GeometryFormatterFactory; import org.elasticsearch.common.geo.GeometryParser; import org.elasticsearch.common.geo.Orientation; import org.elasticsearch.common.geo.ShapeRelation; @@ -174,7 +174,7 @@ public Query geoShapeQuery(Geometry shape, String fieldName, ShapeRelation relat @Override protected Function, List> getFormatter(String format) { - return GeoFormatterFactory.getFormatter(format); + return GeometryFormatterFactory.getFormatter(format, Function.identity()); } } diff --git a/x-pack/plugin/spatial/src/main/java/org/elasticsearch/xpack/spatial/index/mapper/PointFieldMapper.java b/x-pack/plugin/spatial/src/main/java/org/elasticsearch/xpack/spatial/index/mapper/PointFieldMapper.java index 7cf72cd6ddc8a..3ad88844873d3 100644 --- a/x-pack/plugin/spatial/src/main/java/org/elasticsearch/xpack/spatial/index/mapper/PointFieldMapper.java +++ b/x-pack/plugin/spatial/src/main/java/org/elasticsearch/xpack/spatial/index/mapper/PointFieldMapper.java @@ -12,6 +12,7 @@ import org.apache.lucene.search.Query; import org.elasticsearch.common.CheckedBiFunction; import org.elasticsearch.common.Explicit; +import org.elasticsearch.common.geo.GeometryFormatterFactory; import org.elasticsearch.common.geo.ShapeRelation; import org.elasticsearch.common.logging.DeprecationCategory; import org.elasticsearch.common.logging.DeprecationLogger; @@ -25,7 +26,6 @@ import org.elasticsearch.index.mapper.GeoShapeFieldMapper; import org.elasticsearch.index.mapper.MappedFieldType; import org.elasticsearch.index.query.SearchExecutionContext; -import org.elasticsearch.xpack.spatial.common.CartesianFormatterFactory; import org.elasticsearch.xpack.spatial.common.CartesianPoint; import org.elasticsearch.xpack.spatial.index.query.ShapeQueryPointProcessor; @@ -179,8 +179,8 @@ public Query shapeQuery(Geometry shape, String fieldName, ShapeRelation relation } @Override - protected Function, List> getFormatter(String format) { - return CartesianFormatterFactory.getFormatter(format); + protected Function, List> getFormatter(String format) { + return GeometryFormatterFactory.getFormatter(format, p -> new Point(p.getX(), p.getY())); } } @@ -209,11 +209,6 @@ protected CartesianPoint validate(CartesianPoint in) { return in; } - @Override - protected Geometry toGeometry(CartesianPoint point) { - return new Point(point.getX(), point.getY()); - } - @Override protected void reset(CartesianPoint in, double x, double y) { in.reset(x, y); diff --git a/x-pack/plugin/spatial/src/main/java/org/elasticsearch/xpack/spatial/index/mapper/ShapeFieldMapper.java b/x-pack/plugin/spatial/src/main/java/org/elasticsearch/xpack/spatial/index/mapper/ShapeFieldMapper.java index 90ff74665011f..5a1e605410e13 100644 --- a/x-pack/plugin/spatial/src/main/java/org/elasticsearch/xpack/spatial/index/mapper/ShapeFieldMapper.java +++ b/x-pack/plugin/spatial/src/main/java/org/elasticsearch/xpack/spatial/index/mapper/ShapeFieldMapper.java @@ -9,6 +9,7 @@ import org.apache.lucene.document.XYShape; import org.apache.lucene.search.Query; import org.elasticsearch.common.Explicit; +import org.elasticsearch.common.geo.GeometryFormatterFactory; import org.elasticsearch.common.geo.GeometryParser; import org.elasticsearch.common.geo.Orientation; import org.elasticsearch.common.geo.ShapeRelation; @@ -23,7 +24,6 @@ import org.elasticsearch.index.mapper.GeoShapeParser; import org.elasticsearch.index.mapper.MappedFieldType; import org.elasticsearch.index.query.SearchExecutionContext; -import org.elasticsearch.xpack.spatial.common.CartesianFormatterFactory; import org.elasticsearch.xpack.spatial.index.query.ShapeQueryProcessor; import java.io.IOException; @@ -125,7 +125,7 @@ public String typeName() { @Override protected Function, List> getFormatter(String format) { - return CartesianFormatterFactory.getFormatter(format); + return GeometryFormatterFactory.getFormatter(format, Function.identity()); } }