Skip to content

Commit 62c86e3

Browse files
more geo shapes
1 parent fb4ef82 commit 62c86e3

File tree

4 files changed

+125
-6
lines changed

4 files changed

+125
-6
lines changed

spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/aot/AotQueryCreator.java

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,16 @@
2828
import org.springframework.data.domain.ScrollPosition;
2929
import org.springframework.data.domain.Sort;
3030
import org.springframework.data.domain.Vector;
31+
import org.springframework.data.geo.Box;
3132
import org.springframework.data.geo.Circle;
3233
import org.springframework.data.geo.Distance;
3334
import org.springframework.data.geo.Metrics;
3435
import org.springframework.data.geo.Point;
36+
import org.springframework.data.geo.Polygon;
3537
import org.springframework.data.geo.Shape;
3638
import org.springframework.data.mongodb.core.convert.MongoCustomConversions;
3739
import org.springframework.data.mongodb.core.convert.MongoWriter;
40+
import org.springframework.data.mongodb.core.geo.Sphere;
3841
import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
3942
import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
4043
import org.springframework.data.mongodb.core.query.Collation;
@@ -135,6 +138,12 @@ public PlaceholderParameterAccessor(QueryMethod queryMethod) {
135138
placeholders.add(parameter.getIndex(), new PointPlaceholder(parameter.getIndex()));
136139
} else if(ClassUtils.isAssignable(Circle.class, parameter.getType())) {
137140
placeholders.add(parameter.getIndex(), new CirclePlaceholder(parameter.getIndex()));
141+
} else if(ClassUtils.isAssignable(Box.class, parameter.getType())) {
142+
placeholders.add(parameter.getIndex(), new BoxPlaceholder(parameter.getIndex()));
143+
} else if(ClassUtils.isAssignable(Sphere.class, parameter.getType())) {
144+
placeholders.add(parameter.getIndex(), new SpherePlaceholder(parameter.getIndex()));
145+
} else if(ClassUtils.isAssignable(Polygon.class, parameter.getType())) {
146+
placeholders.add(parameter.getIndex(), new PolygonPlaceholder(parameter.getIndex()));
138147
}
139148

140149
else {
@@ -245,6 +254,63 @@ public String toString() {
245254
}
246255
}
247256

257+
static class SpherePlaceholder extends Sphere implements Placeholder {
258+
259+
int index;
260+
public SpherePlaceholder(int index) {
261+
super(new PointPlaceholder(index), Distance.of(1, Metrics.NEUTRAL)); //
262+
this.index = index;
263+
}
264+
265+
@Override
266+
public Object getValue() {
267+
return "?%s".formatted(index);
268+
}
269+
270+
@Override
271+
public String toString() {
272+
return getValue().toString();
273+
}
274+
}
275+
276+
static class BoxPlaceholder extends Box implements Placeholder {
277+
int index;
278+
279+
public BoxPlaceholder(int index) {
280+
super(new PointPlaceholder(index), new PointPlaceholder(index));
281+
this.index = index;
282+
}
283+
284+
@Override
285+
public Object getValue() {
286+
return "?%s".formatted(index);
287+
}
288+
289+
@Override
290+
public String toString() {
291+
return getValue().toString();
292+
}
293+
}
294+
295+
static class PolygonPlaceholder extends Polygon implements Placeholder {
296+
int index;
297+
298+
public PolygonPlaceholder(int index) {
299+
super(new PointPlaceholder(index), new PointPlaceholder(index), new PointPlaceholder(index), new PointPlaceholder(index));
300+
this.index = index;
301+
}
302+
303+
@Override
304+
public Object getValue() {
305+
return "?%s".formatted(index);
306+
}
307+
308+
@Override
309+
public String toString() {
310+
return getValue().toString();
311+
}
312+
}
313+
248314
static class PointPlaceholder extends Point implements Placeholder {
249315

250316
int index;

spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/aot/MongoCodeBlocks.java

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,9 @@
2929
import org.springframework.core.annotation.MergedAnnotation;
3030
import org.springframework.data.domain.SliceImpl;
3131
import org.springframework.data.domain.Sort.Order;
32+
import org.springframework.data.geo.Box;
3233
import org.springframework.data.geo.Circle;
34+
import org.springframework.data.geo.Polygon;
3335
import org.springframework.data.mongodb.core.ExecutableFindOperation.FindWithQuery;
3436
import org.springframework.data.mongodb.core.ExecutableRemoveOperation.ExecutableRemove;
3537
import org.springframework.data.mongodb.core.ExecutableUpdateOperation.ExecutableUpdate;
@@ -39,6 +41,7 @@
3941
import org.springframework.data.mongodb.core.aggregation.AggregationPipeline;
4042
import org.springframework.data.mongodb.core.aggregation.AggregationResults;
4143
import org.springframework.data.mongodb.core.aggregation.TypedAggregation;
44+
import org.springframework.data.mongodb.core.geo.Sphere;
4245
import org.springframework.data.mongodb.core.mapping.MongoSimpleTypes;
4346
import org.springframework.data.mongodb.core.query.BasicQuery;
4447
import org.springframework.data.mongodb.core.query.BasicUpdate;
@@ -694,9 +697,31 @@ static class QueryCodeBlockBuilder {
694697
for (MongoParameter parameter : queryMethod.getParameters().getBindableParameters()) {
695698
String parameterName = context.getParameterName(parameter.getIndex());
696699
if (ClassUtils.isAssignable(Circle.class, parameter.getType())) {
697-
arguments.add(CodeBlock.builder().add("$T.of($L.getCenter(), $L.getRadius().getNormalizedValue())",
698-
List.class, parameterName, parameterName).build());
699-
} else {
700+
arguments.add(CodeBlock.builder()
701+
.add("$T.of($T.of($L.getCenter().getX(), $L.getCenter().getY()), $L.getRadius().getNormalizedValue())",
702+
List.class, List.class, parameterName, parameterName, parameterName)
703+
.build());
704+
} else if (ClassUtils.isAssignable(Box.class, parameter.getType())) {
705+
706+
// { $geoWithin: { $box: [ [ <x1>, <y1> ], [ <x2>, <y2> ] ] }
707+
arguments.add(CodeBlock.builder().add(
708+
"$T.of($T.of($L.getFirst().getX(), $L.getFirst().getY()), $T.of($L.getSecond().getX(), $L.getSecond().getY()))",
709+
List.class, List.class, parameterName, parameterName, List.class, parameterName, parameterName).build());
710+
} else if (ClassUtils.isAssignable(Sphere.class, parameter.getType())) {
711+
// { $centerSphere: [ [ <x>, <y> ], <radius> ] }
712+
arguments.add(CodeBlock.builder()
713+
.add("$T.of($T.of($L.getCenter().getX(), $L.getCenter().getY()), $L.getRadius().getNormalizedValue())",
714+
List.class, List.class, parameterName, parameterName, parameterName)
715+
.build());
716+
} else if (ClassUtils.isAssignable(Polygon.class, parameter.getType())) {
717+
// $polygon: [ [ <x1> , <y1> ], [ <x2> , <y2> ], [ <x3> , <y3> ], ... ]
718+
String localVar = context.localVariable("_p");
719+
arguments
720+
.add(CodeBlock.builder().add("$L.getPoints().stream().map($L -> $T.of($L.getX(), $L.getY())).toList()",
721+
parameterName, localVar, List.class, localVar, localVar).build());
722+
}
723+
724+
else {
700725
arguments.add(CodeBlock.of(parameterName));
701726
}
702727
}

spring-data-mongodb/src/test/java/example/aot/UserRepository.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,13 @@
3232
import org.springframework.data.domain.Slice;
3333
import org.springframework.data.domain.Sort;
3434
import org.springframework.data.domain.Window;
35+
import org.springframework.data.geo.Box;
3536
import org.springframework.data.geo.Circle;
3637
import org.springframework.data.geo.Point;
38+
import org.springframework.data.geo.Polygon;
3739
import org.springframework.data.mongodb.core.aggregation.AggregationResults;
3840
import org.springframework.data.mongodb.repository.Aggregation;
3941
import org.springframework.data.mongodb.repository.Hint;
40-
import org.springframework.data.mongodb.repository.Person;
4142
import org.springframework.data.mongodb.repository.Query;
4243
import org.springframework.data.mongodb.repository.ReadPreference;
4344
import org.springframework.data.mongodb.repository.Update;
@@ -110,6 +111,10 @@ public interface UserRepository extends CrudRepository<User, String> {
110111

111112
List<User> findByLocationCoordinatesWithin(Circle circle);
112113

114+
List<User> findByLocationCoordinatesWithin(Box box);
115+
116+
List<User> findByLocationCoordinatesWithin(Polygon polygon);
117+
113118
// TODO: GeoQueries
114119
// TODO: TextSearch
115120

spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/aot/MongoRepositoryContributorTests.java

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,10 @@
4545
import org.springframework.data.domain.Slice;
4646
import org.springframework.data.domain.Sort;
4747
import org.springframework.data.domain.Window;
48+
import org.springframework.data.geo.Box;
4849
import org.springframework.data.geo.Circle;
4950
import org.springframework.data.geo.Point;
51+
import org.springframework.data.geo.Polygon;
5052
import org.springframework.data.mongodb.core.MongoOperations;
5153
import org.springframework.data.mongodb.core.MongoTemplate;
5254
import org.springframework.data.mongodb.core.aggregation.AggregationResults;
@@ -619,13 +621,34 @@ void testNearWithGeoJson() {
619621
}
620622

621623
@Test
622-
void testGeoWithin() {
624+
void testGeoWithinCircle() {
623625

624626
List<User> users = fragment.findByLocationCoordinatesWithin(new Circle(-78.99171, 45.738868, 170));
625627
assertThat(users).extracting(User::getUsername).containsExactly("leia");
626628
}
627629

628-
//List<Person> result = repository.findByLocationWithin();
630+
@Test
631+
void testWithinBox() {
632+
633+
Box box = new Box(new Point(-78.99171, 35.738868), new Point(-68.99171, 45.738868));
634+
635+
List<User> result = fragment.findByLocationCoordinatesWithin(box);
636+
assertThat(result).extracting(User::getUsername).containsExactly("leia");
637+
}
638+
639+
@Test
640+
void findsPeopleByLocationWithinPolygon() {
641+
642+
Point first = new Point(-78.99171, 35.738868);
643+
Point second = new Point(-78.99171, 45.738868);
644+
Point third = new Point(-68.99171, 45.738868);
645+
Point fourth = new Point(-68.99171, 35.738868);
646+
647+
List<User> result = fragment.findByLocationCoordinatesWithin(new Polygon(first, second, third, fourth));
648+
assertThat(result).extracting(User::getUsername).containsExactly("leia");
649+
}
650+
651+
629652

630653
private static void initUsers() {
631654

0 commit comments

Comments
 (0)