Skip to content

Commit 7689e5b

Browse files
geo resut conversion -> still need to have the paging variant
1 parent 25ae2fa commit 7689e5b

File tree

4 files changed

+91
-22
lines changed

4 files changed

+91
-22
lines changed

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

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@
3232
import org.springframework.data.geo.Box;
3333
import org.springframework.data.geo.Circle;
3434
import org.springframework.data.geo.Distance;
35+
import org.springframework.data.geo.GeoPage;
36+
import org.springframework.data.geo.GeoResults;
3537
import org.springframework.data.geo.Polygon;
3638
import org.springframework.data.mongodb.core.ExecutableFindOperation.FindWithQuery;
3739
import org.springframework.data.mongodb.core.ExecutableRemoveOperation.ExecutableRemove;
@@ -505,29 +507,46 @@ CodeBlock build() {
505507
String minVarName = context.localVariable("min");
506508
String maxVarName = context.localVariable("max");
507509

508-
builder.beginControlFlow("if($L.getLowerBound().isPresent())", rangeParametername);
509-
builder.addStatement("$1T $2L = $3L.getLowerBound().get()", Distance.class, minVarName, rangeParametername);
510-
builder.addStatement("$1L.minDistance($2L.getValue()).in($2L.getMetric())", variableName, minVarName);
510+
builder.beginControlFlow("if($L.getLowerBound().isBounded())", rangeParametername);
511+
builder.addStatement("$1T $2L = $3L.getLowerBound().getValue().get()", Distance.class, minVarName,
512+
rangeParametername);
513+
builder.addStatement("$1L.minDistance($2L).in($2L.getMetric())", variableName, minVarName);
511514
builder.endControlFlow();
512515

513-
builder.beginControlFlow("if($L.getUpperBound().isPresent())", rangeParametername);
514-
builder.addStatement("$1T $2L = $3L.getUpperBound().get()", Distance.class, maxVarName, rangeParametername);
515-
builder.addStatement("$1L.maxDistance($2L.getValue()).in($2L.getMetric())", variableName, maxVarName);
516+
builder.beginControlFlow("if($L.getUpperBound().isBounded())", rangeParametername);
517+
builder.addStatement("$1T $2L = $3L.getUpperBound().getValue().get()", Distance.class, maxVarName,
518+
rangeParametername);
519+
builder.addStatement("$1L.maxDistance($2L).in($2L.getMetric())", variableName, maxVarName);
516520
builder.endControlFlow();
517521
} else {
518522

519523
String distanceParametername = context.getParameterName(queryMethod.getParameters().getMaxDistanceIndex());
520-
builder.addStatement("$1L.maxDistance($2L.getValue()).in($2L.getMetric())", variableName,
521-
distanceParametername);
524+
builder.addStatement("$1L.maxDistance($2L).in($2L.getMetric())", variableName, distanceParametername);
522525
}
523526

524527
if (context.getPageableParameterName() != null) {
525528
builder.addStatement("$L.with($L)", variableName, context.getPageableParameterName());
526529
}
527530

528531
builder.add("\n");
529-
builder.addStatement("return $L.query($T.class).near($L).all()", context.fieldNameOf(MongoOperations.class),
530-
context.getRepositoryInformation().getDomainType(), variableName);
532+
533+
// TODO: move the section below into dedicated executor builder
534+
if (ClassUtils.isAssignable(GeoPage.class, context.getReturnType().getRawClass())) {
535+
builder.addStatement("return new $T<>($L.query($T.class).near($L).all())", GeoPage.class,
536+
context.fieldNameOf(MongoOperations.class), context.getRepositoryInformation().getDomainType(),
537+
variableName);
538+
}
539+
540+
else if (ClassUtils.isAssignable(GeoResults.class, context.getReturnType().getRawClass())) {
541+
542+
builder.addStatement("return $L.query($T.class).near($L).all()", context.fieldNameOf(MongoOperations.class),
543+
context.getRepositoryInformation().getDomainType(), variableName);
544+
} else {
545+
builder.addStatement("return $L.query($T.class).near($L).all().getContent()",
546+
context.fieldNameOf(MongoOperations.class), context.getRepositoryInformation().getDomainType(),
547+
variableName);
548+
}
549+
531550
return builder.build();
532551
}
533552

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ protected void customizeConstructor(AotRepositoryConstructorBuilder constructorB
9595
return aggregationMethodContributor(queryMethod, aggregation);
9696
}
9797

98-
if(queryMethod.isGeoNearQuery()) {
98+
if(queryMethod.isGeoNearQuery() || (queryMethod.getParameters().getMaxDistanceIndex() != -1 && queryMethod.getReturnType().isCollectionLike())) {
9999
NearQueryInteraction near = new NearQueryInteraction();
100100
return nearQueryMethodContributor(queryMethod, near);
101101
}

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

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,16 @@
2828
import org.springframework.data.domain.Limit;
2929
import org.springframework.data.domain.Page;
3030
import org.springframework.data.domain.Pageable;
31+
import org.springframework.data.domain.Range;
3132
import org.springframework.data.domain.ScrollPosition;
3233
import org.springframework.data.domain.Slice;
3334
import org.springframework.data.domain.Sort;
3435
import org.springframework.data.domain.Window;
3536
import org.springframework.data.geo.Box;
3637
import org.springframework.data.geo.Circle;
3738
import org.springframework.data.geo.Distance;
39+
import org.springframework.data.geo.GeoPage;
40+
import org.springframework.data.geo.GeoResult;
3841
import org.springframework.data.geo.GeoResults;
3942
import org.springframework.data.geo.Point;
4043
import org.springframework.data.geo.Polygon;
@@ -120,7 +123,12 @@ public interface UserRepository extends CrudRepository<User, String> {
120123

121124
GeoResults<User> findByLocationCoordinatesNear(Point point, Distance maxDistance);
122125

123-
// TODO: GeoQueries
126+
List<GeoResult<User>> findUserAsListByLocationCoordinatesNear(Point point, Distance maxDistance);
127+
128+
GeoResults<User> findByLocationCoordinatesNear(Point point, Range<Distance> distance);
129+
130+
GeoPage<User> findByLocationCoordinatesNear(Point point, Distance maxDistance, Pageable pageable);
131+
124132
// TODO: TextSearch
125133

126134
/* Annotated Queries */

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

Lines changed: 52 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -41,13 +41,16 @@
4141
import org.springframework.data.domain.OffsetScrollPosition;
4242
import org.springframework.data.domain.Page;
4343
import org.springframework.data.domain.PageRequest;
44+
import org.springframework.data.domain.Range;
4445
import org.springframework.data.domain.ScrollPosition;
4546
import org.springframework.data.domain.Slice;
4647
import org.springframework.data.domain.Sort;
4748
import org.springframework.data.domain.Window;
4849
import org.springframework.data.geo.Box;
4950
import org.springframework.data.geo.Circle;
5051
import org.springframework.data.geo.Distance;
52+
import org.springframework.data.geo.GeoPage;
53+
import org.springframework.data.geo.GeoResult;
5154
import org.springframework.data.geo.GeoResults;
5255
import org.springframework.data.geo.Metrics;
5356
import org.springframework.data.geo.Point;
@@ -96,7 +99,7 @@ MongoOperations mongoOperations() {
9699
@BeforeAll
97100
static void beforeAll() {
98101
client.getDatabase(DB_NAME).getCollection("user").createIndex(new Document("location.coordinates", "2d"),
99-
new IndexOptions());
102+
new IndexOptions());
100103
}
101104

102105
@BeforeEach
@@ -613,21 +616,21 @@ void testAggregationWithCollation() {
613616
void testNear() {
614617

615618
List<User> users = fragment.findByLocationCoordinatesNear(new Point(-73.99171, 40.738868));
616-
assertThat(users).extracting(User::getUsername).containsExactly("leia");
619+
assertThat(users).extracting(User::getUsername).containsExactly("leia", "vader");
617620
}
618621

619622
@Test
620623
void testNearWithGeoJson() {
621624

622625
List<User> users = fragment.findByLocationCoordinatesNear(new GeoJsonPoint(-73.99171, 40.738868));
623-
assertThat(users).extracting(User::getUsername).containsExactly("leia");
626+
assertThat(users).extracting(User::getUsername).containsExactly("leia", "vader");
624627
}
625628

626629
@Test
627630
void testGeoWithinCircle() {
628631

629632
List<User> users = fragment.findByLocationCoordinatesWithin(new Circle(-78.99171, 45.738868, 170));
630-
assertThat(users).extracting(User::getUsername).containsExactly("leia");
633+
assertThat(users).extracting(User::getUsername).containsExactly("leia", "vader");
631634
}
632635

633636
@Test
@@ -636,7 +639,7 @@ void testWithinBox() {
636639
Box box = new Box(new Point(-78.99171, 35.738868), new Point(-68.99171, 45.738868));
637640

638641
List<User> result = fragment.findByLocationCoordinatesWithin(box);
639-
assertThat(result).extracting(User::getUsername).containsExactly("leia");
642+
assertThat(result).extracting(User::getUsername).containsExactly("leia", "vader");
640643
}
641644

642645
@Test
@@ -648,18 +651,51 @@ void findsPeopleByLocationWithinPolygon() {
648651
Point fourth = new Point(-68.99171, 35.738868);
649652

650653
List<User> result = fragment.findByLocationCoordinatesWithin(new Polygon(first, second, third, fourth));
651-
assertThat(result).extracting(User::getUsername).containsExactly("leia");
654+
assertThat(result).extracting(User::getUsername).containsExactly("leia", "vader");
652655
}
653656

654-
655657
@Test
656658
void testNearWithGeoResult() {
657659

658-
GeoResults<User> users = fragment.findByLocationCoordinatesNear(new Point(-73.99, 40.73), Distance.of(2000, Metrics.KILOMETERS));
659-
System.out.println("users: " + users);
660-
assertThat(users).isNotEmpty();
660+
GeoResults<User> users = fragment.findByLocationCoordinatesNear(new Point(-73.99, 40.73),
661+
Distance.of(5, Metrics.KILOMETERS));
662+
assertThat(users).extracting(GeoResult::getContent).extracting(User::getUsername).containsExactly("leia");
663+
}
664+
665+
@Test
666+
void testNearReturningListOfGeoResult() {
667+
668+
List<GeoResult<User>> users = fragment.findUserAsListByLocationCoordinatesNear(new Point(-73.99, 40.73),
669+
Distance.of(5, Metrics.KILOMETERS));
670+
assertThat(users).extracting(GeoResult::getContent).extracting(User::getUsername).containsExactly("leia");
671+
}
672+
673+
@Test
674+
void testNearWithRange() {
675+
676+
Range<Distance> range = Distance.between(Distance.of(5, Metrics.KILOMETERS), Distance.of(2000, Metrics.KILOMETERS));
677+
GeoResults<User> users = fragment.findByLocationCoordinatesNear(new Point(-73.99, 40.73), range);
678+
679+
assertThat(users).extracting(GeoResult::getContent).extracting(User::getUsername).containsExactly("vader");
661680
}
662681

682+
@Test
683+
void testNearReturningGeoPage() {
684+
685+
// TODO: still need to create the count and extract the total elements
686+
GeoPage<User> page1 = fragment.findByLocationCoordinatesNear(new Point(-73.99, 40.73),
687+
Distance.of(2000, Metrics.KILOMETERS), PageRequest.of(0, 1));
688+
689+
assertThat(page1.hasNext()).isTrue();
690+
691+
GeoPage<User> page2 = fragment.findByLocationCoordinatesNear(new Point(-73.99, 40.73),
692+
Distance.of(2000, Metrics.KILOMETERS), page1.nextPageable());
693+
assertThat(page2.hasNext()).isFalse();
694+
}
695+
696+
/**
697+
* GeoResults<Person> results = repository.findPersonByLocationNear(new Point(-73.99, 40.73), range);
698+
*/
663699
private static void initUsers() {
664700

665701
Document luke = Document.parse("""
@@ -753,6 +789,12 @@ private static void initUsers() {
753789
"username": "vader",
754790
"first_name": "Anakin",
755791
"last_name": "Skywalker",
792+
"location" : {
793+
"planet" : "Death Star",
794+
"coordinates" : {
795+
"x" : -73.9, "y" : 40.7
796+
}
797+
},
756798
"visits" : 50,
757799
"posts": [
758800
{

0 commit comments

Comments
 (0)