@@ -65,76 +65,187 @@ class _GeometryValidationFilter extends FieldBasedFilter {
6565 }
6666}
6767
68- ///@nodoc
69- class WithinFilter extends SpatialFilter implements FlattenableFilter {
70- WithinFilter (super .field, super .value);
68+ /// Internal implementation of WithinFilter for index scanning only.
69+ /// Does not implement FlattenableFilter to avoid infinite recursion.
70+ class WithinIndexFilter extends SpatialFilter {
71+ WithinIndexFilter (super .field, super .value);
72+
73+ @override
74+ Stream <dynamic > applyOnIndex (IndexMap indexMap) {
75+ // calculated from SpatialIndex
76+ return const Stream .empty ();
77+ }
78+
79+ @override
80+ String toString () {
81+ return '($field within $value )' ;
82+ }
83+ }
84+
85+ /// Internal implementation of IntersectsFilter for index scanning only.
86+ /// Does not implement FlattenableFilter to avoid infinite recursion.
87+ class IntersectsIndexFilter extends SpatialFilter {
88+ IntersectsIndexFilter (super .field, super .value);
7189
7290 @override
7391 Stream <dynamic > applyOnIndex (IndexMap indexMap) {
7492 // calculated from SpatialIndex
7593 return const Stream .empty ();
7694 }
7795
96+ @override
97+ String toString () {
98+ return '($field intersects $value )' ;
99+ }
100+ }
101+
102+ ///@nodoc
103+ class WithinFilter extends Filter implements FlattenableFilter {
104+ final String field;
105+ final Geometry geometry;
106+
107+ WithinFilter (this .field, this .geometry);
108+
109+ @override
110+ bool apply (Document doc) {
111+ // This should not be called directly as the filter is flattened
112+ return false ;
113+ }
114+
78115 @override
79116 List <Filter > getFilters () {
80- // Return two filters: one for index scan (this) , one for validation
117+ // Return two filters: one for index scan, one for validation
81118 return [
82- this ,
119+ WithinIndexFilter (field, geometry) ,
83120 _GeometryValidationFilter (
84121 field,
85- value ,
122+ geometry ,
86123 (docGeom, filterGeom) => docGeom.within (filterGeom),
87124 ),
88125 ];
89126 }
90127
91128 @override
92129 String toString () {
93- return '($field within $value )' ;
130+ return '($field within $geometry )' ;
94131 }
95132}
96133
97134///@nodoc
98- class IntersectsFilter extends SpatialFilter implements FlattenableFilter {
99- IntersectsFilter (super .field, super .value);
135+ class IntersectsFilter extends Filter implements FlattenableFilter {
136+ final String field;
137+ final Geometry geometry;
138+
139+ IntersectsFilter (this .field, this .geometry);
100140
101141 @override
102- Stream < dynamic > applyOnIndex ( IndexMap indexMap ) {
103- // calculated from SpatialIndex
104- return const Stream . empty () ;
142+ bool apply ( Document doc ) {
143+ // This should not be called directly as the filter is flattened
144+ return false ;
105145 }
106146
107147 @override
108148 List <Filter > getFilters () {
109- // Return two filters: one for index scan (this) , one for validation
149+ // Return two filters: one for index scan, one for validation
110150 return [
111- this ,
151+ IntersectsIndexFilter (field, geometry) ,
112152 _GeometryValidationFilter (
113153 field,
114- value ,
154+ geometry ,
115155 (docGeom, filterGeom) => docGeom.intersects (filterGeom),
116156 ),
117157 ];
118158 }
119159
120160 @override
121161 String toString () {
122- return '($field intersects $value )' ;
162+ return '($field intersects $geometry )' ;
123163 }
124164}
125165
126166///@nodoc
127- class NearFilter extends WithinFilter {
167+ class NearFilter extends Filter implements FlattenableFilter {
168+ final String field;
169+ final Geometry circle;
170+ final Coordinate center;
171+ final double radius;
172+
128173 factory NearFilter (String field, Coordinate center, double radius) {
129- var geometry = _createCircle (center, radius);
130- return NearFilter ._(field, geometry );
174+ var circle = _createCircle (center, radius);
175+ return NearFilter ._(field, circle, center, radius );
131176 }
132177
133178 factory NearFilter .fromPoint (String field, Point point, double radius) {
134- return NearFilter ._(field, _createCircle (point.getCoordinate (), radius));
179+ var center = point.getCoordinate ();
180+ var circle = _createCircle (center, radius);
181+ return NearFilter ._(field, circle, center! , radius);
182+ }
183+
184+ NearFilter ._(this .field, this .circle, this .center, this .radius);
185+
186+ @override
187+ bool apply (Document doc) {
188+ // This should not be called directly as the filter is flattened
189+ return false ;
190+ }
191+
192+ @override
193+ List <Filter > getFilters () {
194+ // Return two filters: one for index scan (using within), one for distance validation
195+ return [
196+ WithinIndexFilter (field, circle),
197+ _NearValidationFilter (field, center, radius),
198+ ];
199+ }
200+
201+ @override
202+ String toString () {
203+ return '($field near $center within $radius )' ;
135204 }
205+ }
206+
207+ /// Validation filter for near queries that checks actual distance.
208+ class _NearValidationFilter extends Filter {
209+ final String field;
210+ final Coordinate center;
211+ final double radius;
212+
213+ _NearValidationFilter (this .field, this .center, this .radius);
214+
215+ @override
216+ bool apply (Document doc) {
217+ var fieldValue = doc.get (field);
218+ if (fieldValue == null ) {
219+ return false ;
220+ }
221+
222+ Geometry ? documentGeometry;
223+ if (fieldValue is Geometry ) {
224+ documentGeometry = fieldValue;
225+ } else if (fieldValue is String ) {
226+ try {
227+ var reader = WKTReader ();
228+ documentGeometry = reader.read (fieldValue);
229+ } catch (e) {
230+ return false ;
231+ }
232+ } else {
233+ return false ;
234+ }
136235
137- NearFilter ._(super .field, super .geometry);
236+ // For near queries, check if the geometry is within the distance
237+ // For points, check direct distance. For other geometries, check if they intersect the circle.
238+ if (documentGeometry is Point ) {
239+ var coord = documentGeometry.getCoordinate ();
240+ if (coord == null ) return false ;
241+ var distance = center.distance (coord);
242+ return distance <= radius;
243+ } else {
244+ // For non-point geometries, check if they intersect the circle
245+ var circle = _createCircle (center, radius);
246+ return documentGeometry! .intersects (circle);
247+ }
248+ }
138249}
139250
140251Geometry _createCircle (Coordinate ? center, double radius) {
0 commit comments