2020package org .elasticsearch .index .query ;
2121
2222import org .apache .lucene .document .LatLonShape ;
23- import org .apache .lucene .document .ShapeField ;
24- import org .apache .lucene .geo .Line ;
25- import org .apache .lucene .geo .Polygon ;
26- import org .apache .lucene .search .BooleanClause ;
27- import org .apache .lucene .search .BooleanQuery ;
23+ import org .apache .lucene .geo .LatLonGeometry ;
2824import org .apache .lucene .search .MatchNoDocsQuery ;
2925import org .apache .lucene .search .Query ;
3026import org .elasticsearch .Version ;
27+ import org .elasticsearch .common .geo .GeoLineDecomposer ;
28+ import org .elasticsearch .common .geo .GeoPolygonDecomposer ;
29+ import org .elasticsearch .common .geo .GeoShapeUtils ;
3130import org .elasticsearch .common .geo .ShapeRelation ;
3231import org .elasticsearch .geometry .Circle ;
3332import org .elasticsearch .geometry .Geometry ;
3433import org .elasticsearch .geometry .GeometryCollection ;
3534import org .elasticsearch .geometry .GeometryVisitor ;
35+ import org .elasticsearch .geometry .Line ;
3636import org .elasticsearch .geometry .LinearRing ;
3737import org .elasticsearch .geometry .MultiLine ;
3838import org .elasticsearch .geometry .MultiPoint ;
3939import org .elasticsearch .geometry .MultiPolygon ;
4040import org .elasticsearch .geometry .Point ;
41+ import org .elasticsearch .geometry .Polygon ;
4142import org .elasticsearch .geometry .Rectangle ;
4243import org .elasticsearch .index .mapper .AbstractSearchableGeometryFieldType ;
43- import org .elasticsearch .index .mapper .GeoShapeFieldMapper ;
44- import org .elasticsearch .index .mapper .GeoShapeIndexer ;
45- import org .elasticsearch .index .mapper .MappedFieldType ;
4644
47- import static org .elasticsearch .index .mapper .GeoShapeIndexer .toLucenePolygon ;
45+
46+ import java .util .ArrayList ;
47+ import java .util .List ;
48+
4849
4950public class VectorGeoShapeQueryProcessor implements AbstractSearchableGeometryFieldType .QueryProcessor {
5051
@@ -59,127 +60,126 @@ public Query process(Geometry shape, String fieldName, ShapeRelation relation, Q
5960 return getVectorQueryFromShape (shape , fieldName , relation , context );
6061 }
6162
62- protected Query getVectorQueryFromShape (
63- Geometry queryShape , String fieldName , ShapeRelation relation , QueryShardContext context ) {
64- GeoShapeIndexer geometryIndexer = new GeoShapeIndexer (true , fieldName );
65-
66- Geometry processedShape = geometryIndexer .prepareForIndexing (queryShape );
67-
68- if (processedShape == null ) {
63+ private Query getVectorQueryFromShape (Geometry queryShape , String fieldName , ShapeRelation relation , QueryShardContext context ) {
64+ final LuceneGeometryCollector visitor = new LuceneGeometryCollector (fieldName , context );
65+ queryShape .visit (visitor );
66+ final List <LatLonGeometry > geometries = visitor .geometries ();
67+ if (geometries .size () == 0 ) {
6968 return new MatchNoDocsQuery ();
7069 }
71- return processedShape .visit (new ShapeVisitor (context , fieldName , relation ));
70+ return LatLonShape .newGeometryQuery (fieldName , relation .getLuceneRelation (),
71+ geometries .toArray (new LatLonGeometry [geometries .size ()]));
7272 }
7373
74- private class ShapeVisitor implements GeometryVisitor <Query , RuntimeException > {
75- QueryShardContext context ;
76- MappedFieldType fieldType ;
77- String fieldName ;
78- ShapeRelation relation ;
74+ private static class LuceneGeometryCollector implements GeometryVisitor <Void , RuntimeException > {
75+ private final List <LatLonGeometry > geometries = new ArrayList <>();
76+ private final String name ;
77+ private final QueryShardContext context ;
7978
80- ShapeVisitor (QueryShardContext context , String fieldName , ShapeRelation relation ) {
79+ private LuceneGeometryCollector (String name , QueryShardContext context ) {
80+ this .name = name ;
8181 this .context = context ;
82- this .fieldType = context .fieldMapper (fieldName );
83- this .fieldName = fieldName ;
84- this .relation = relation ;
8582 }
8683
87- @ Override
88- public Query visit (Circle circle ) {
89- throw new QueryShardException (context , "Field [" + fieldName + "] found an unknown shape Circle" );
84+ List <LatLonGeometry > geometries () {
85+ return geometries ;
9086 }
9187
9288 @ Override
93- public Query visit (GeometryCollection <?> collection ) {
94- BooleanQuery .Builder bqb = new BooleanQuery .Builder ();
95- visit (bqb , collection );
96- return bqb .build ();
97- }
98-
99- private void visit (BooleanQuery .Builder bqb , GeometryCollection <?> collection ) {
100- BooleanClause .Occur occur ;
101- if (relation == ShapeRelation .CONTAINS || relation == ShapeRelation .DISJOINT ) {
102- // all shapes must be disjoint / must be contained in relation to the indexed shape.
103- occur = BooleanClause .Occur .MUST ;
104- } else {
105- // at least one shape must intersect / contain the indexed shape.
106- occur = BooleanClause .Occur .SHOULD ;
89+ public Void visit (Circle circle ) {
90+ if (circle .isEmpty () == false ) {
91+ geometries .add (GeoShapeUtils .toLuceneCircle (circle ));
10792 }
93+ return null ;
94+ }
95+
96+ @ Override
97+ public Void visit (GeometryCollection <?> collection ) {
10898 for (Geometry shape : collection ) {
109- bqb . add ( shape .visit (this ), occur );
99+ shape .visit (this );
110100 }
101+ return null ;
111102 }
112103
113104 @ Override
114- public Query visit (org .elasticsearch .geometry .Line line ) {
115- validateIsGeoShapeFieldType ();
116- return LatLonShape .newLineQuery (fieldName , relation .getLuceneRelation (), new Line (line .getY (), line .getX ()));
105+ public Void visit (org .elasticsearch .geometry .Line line ) {
106+ if (line .isEmpty () == false ) {
107+ List <org .elasticsearch .geometry .Line > collector = new ArrayList <>();
108+ GeoLineDecomposer .decomposeLine (line , collector );
109+ collectLines (collector );
110+ }
111+ return null ;
117112 }
118113
119114 @ Override
120- public Query visit (LinearRing ring ) {
121- throw new QueryShardException (context , "Field [" + fieldName + "] found an unsupported shape LinearRing" );
115+ public Void visit (LinearRing ring ) {
116+ throw new QueryShardException (context , "Field [" + name + "] found and unsupported shape LinearRing" );
122117 }
123118
124119 @ Override
125- public Query visit (MultiLine multiLine ) {
126- validateIsGeoShapeFieldType ();
127- Line [] lines = new Line [multiLine .size ()];
128- for (int i = 0 ; i < multiLine .size (); i ++) {
129- lines [i ] = new Line (multiLine .get (i ).getY (), multiLine .get (i ).getX ());
130- }
131- return LatLonShape .newLineQuery (fieldName , relation .getLuceneRelation (), lines );
120+ public Void visit (MultiLine multiLine ) {
121+ List <org .elasticsearch .geometry .Line > collector = new ArrayList <>();
122+ GeoLineDecomposer .decomposeMultiLine (multiLine , collector );
123+ collectLines (collector );
124+ return null ;
132125 }
133126
134127 @ Override
135- public Query visit (MultiPoint multiPoint ) {
136- double [][] points = new double [multiPoint .size ()][2 ];
137- for (int i = 0 ; i < multiPoint .size (); i ++) {
138- points [i ] = new double [] {multiPoint .get (i ).getLat (), multiPoint .get (i ).getLon ()};
128+ public Void visit (MultiPoint multiPoint ) {
129+ for (Point point : multiPoint ) {
130+ visit (point );
139131 }
140- return LatLonShape . newPointQuery ( fieldName , relation . getLuceneRelation (), points ) ;
132+ return null ;
141133 }
142134
143135 @ Override
144- public Query visit (MultiPolygon multiPolygon ) {
145- Polygon [] polygons = new Polygon [multiPolygon .size ()];
146- for (int i = 0 ; i < multiPolygon .size (); i ++) {
147- polygons [i ] = toLucenePolygon (multiPolygon .get (i ));
136+ public Void visit (MultiPolygon multiPolygon ) {
137+ if (multiPolygon .isEmpty () == false ) {
138+ List <org .elasticsearch .geometry .Polygon > collector = new ArrayList <>();
139+ GeoPolygonDecomposer .decomposeMultiPolygon (multiPolygon , true , collector );
140+ collectPolygons (collector );
148141 }
149- return LatLonShape . newPolygonQuery ( fieldName , relation . getLuceneRelation (), polygons ) ;
142+ return null ;
150143 }
151144
152145 @ Override
153- public Query visit (Point point ) {
154- validateIsGeoShapeFieldType ();
155- ShapeField .QueryRelation luceneRelation = relation .getLuceneRelation ();
156- if (luceneRelation == ShapeField .QueryRelation .CONTAINS ) {
157- // contains and intersects are equivalent but the implementation of
158- // intersects is more efficient.
159- luceneRelation = ShapeField .QueryRelation .INTERSECTS ;
146+ public Void visit (Point point ) {
147+ if (point .isEmpty () == false ) {
148+ geometries .add (GeoShapeUtils .toLucenePoint (point ));
160149 }
161- return LatLonShape . newPointQuery ( fieldName , luceneRelation ,
162- new double [] { point . getY (), point . getX ()});
150+ return null ;
151+
163152 }
164153
165154 @ Override
166- public Query visit (org .elasticsearch .geometry .Polygon polygon ) {
167- return LatLonShape .newPolygonQuery (fieldName , relation .getLuceneRelation (), toLucenePolygon (polygon ));
155+ public Void visit (org .elasticsearch .geometry .Polygon polygon ) {
156+ if (polygon .isEmpty () == false ) {
157+ List <org .elasticsearch .geometry .Polygon > collector = new ArrayList <>();
158+ GeoPolygonDecomposer .decomposePolygon (polygon , true , collector );
159+ collectPolygons (collector );
160+ }
161+ return null ;
168162 }
169163
170164 @ Override
171- public Query visit (Rectangle r ) {
172- return LatLonShape .newBoxQuery (fieldName , relation .getLuceneRelation (),
173- r .getMinY (), r .getMaxY (), r .getMinX (), r .getMaxX ());
165+ public Void visit (Rectangle r ) {
166+ if (r .isEmpty () == false ) {
167+ geometries .add (GeoShapeUtils .toLuceneRectangle (r ));
168+ }
169+ return null ;
174170 }
175171
176- private void validateIsGeoShapeFieldType () {
177- if (fieldType instanceof GeoShapeFieldMapper .GeoShapeFieldType == false ) {
178- throw new QueryShardException (context , "Expected " + GeoShapeFieldMapper .CONTENT_TYPE
179- + " field type for Field [" + fieldName + "] but found " + fieldType .typeName ());
172+ private void collectLines (List <org .elasticsearch .geometry .Line > geometryLines ) {
173+ for (Line line : geometryLines ) {
174+ geometries .add (GeoShapeUtils .toLuceneLine (line ));
180175 }
181176 }
182- }
183177
178+ private void collectPolygons (List <org .elasticsearch .geometry .Polygon > geometryPolygons ) {
179+ for (Polygon polygon : geometryPolygons ) {
180+ geometries .add (GeoShapeUtils .toLucenePolygon (polygon ));
181+ }
182+ }
183+ }
184184}
185185
0 commit comments