Skip to content

Commit 9797cb5

Browse files
committed
feat: Add example for query
1 parent 9725374 commit 9797cb5

File tree

3 files changed

+106
-10
lines changed

3 files changed

+106
-10
lines changed
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/*
2+
* Copyright 2025 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package example.springdata.mongodb.customer;
17+
18+
import lombok.Data;
19+
import org.springframework.data.mongodb.core.geo.GeoJsonPolygon;
20+
import org.springframework.data.mongodb.core.index.GeoSpatialIndexType;
21+
import org.springframework.data.mongodb.core.index.GeoSpatialIndexed;
22+
import org.springframework.data.mongodb.core.mapping.Document;
23+
import org.springframework.util.Assert;
24+
25+
/**
26+
* An entity to represent a Store with a service area.
27+
*
28+
* @author Rishabh Saraswat
29+
*/
30+
@Data
31+
@Document
32+
public class Store {
33+
34+
private String id;
35+
private final String name;
36+
@GeoSpatialIndexed(type = GeoSpatialIndexType.GEO_2DSPHERE)
37+
private final GeoJsonPolygon serviceArea; // unlike Polygon, GeoJsonPolygon is closed boundary
38+
39+
/**
40+
* Creates a new {@link Store} with the given name and service area.
41+
*
42+
* @param name must not be {@literal null} or empty.
43+
* @param serviceArea must not be {@literal null}.
44+
*/
45+
public Store(String name, GeoJsonPolygon serviceArea) {
46+
Assert.hasText(name, "Name must not be empty");
47+
Assert.notNull(serviceArea, "Service area must not be null");
48+
this.name = name;
49+
this.serviceArea = serviceArea;
50+
}
51+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package example.springdata.mongodb.customer;
2+
3+
import org.springframework.data.repository.CrudRepository;
4+
5+
/**
6+
* Repository interface for {@link Store} instances.
7+
*
8+
* @author Rishabh Saraswat
9+
*/
10+
interface StoreRepository extends CrudRepository<Store, String>{
11+
}

mongodb/example/src/test/java/example/springdata/mongodb/customer/CustomerRepositoryIntegrationTest.java

Lines changed: 44 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2014-2021 the original author or authors.
2+
* Copyright 2014-2025 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -15,43 +15,47 @@
1515
*/
1616
package example.springdata.mongodb.customer;
1717

18-
import static org.assertj.core.api.Assertions.*;
19-
import static org.assertj.core.data.Offset.offset;
20-
2118
import example.springdata.mongodb.util.MongoContainers;
22-
23-
import java.util.stream.Stream;
24-
2519
import org.junit.jupiter.api.BeforeEach;
2620
import org.junit.jupiter.api.Test;
27-
2821
import org.springframework.beans.factory.annotation.Autowired;
2922
import org.springframework.boot.test.autoconfigure.data.mongo.DataMongoTest;
3023
import org.springframework.data.domain.Limit;
3124
import org.springframework.data.geo.Distance;
3225
import org.springframework.data.geo.Metrics;
3326
import org.springframework.data.geo.Point;
27+
import org.springframework.data.geo.Polygon;
3428
import org.springframework.data.mongodb.core.MongoOperations;
29+
import org.springframework.data.mongodb.core.geo.GeoJsonPoint;
30+
import org.springframework.data.mongodb.core.geo.GeoJsonPolygon;
3531
import org.springframework.data.mongodb.core.index.GeospatialIndex;
32+
import org.springframework.data.mongodb.core.query.Criteria;
33+
import org.springframework.data.mongodb.core.query.Query;
3634
import org.springframework.data.querydsl.QSort;
3735
import org.springframework.test.context.DynamicPropertyRegistry;
3836
import org.springframework.test.context.DynamicPropertySource;
39-
4037
import org.testcontainers.containers.MongoDBContainer;
4138
import org.testcontainers.junit.jupiter.Container;
4239
import org.testcontainers.junit.jupiter.Testcontainers;
4340

41+
import java.util.List;
42+
import java.util.stream.Stream;
43+
44+
import static org.assertj.core.api.Assertions.assertThat;
45+
import static org.assertj.core.data.Offset.offset;
46+
4447
/**
4548
* Integration test for {@link CustomerRepository}.
4649
*
4750
* @author Oliver Gierke
51+
* @author Rishabh Saraswat
4852
*/
4953
@Testcontainers
5054
@DataMongoTest
5155
class CustomerRepositoryIntegrationTest {
5256

5357
@Container //
54-
private static MongoDBContainer mongoDBContainer = MongoContainers.getDefaultContainer();
58+
private static final MongoDBContainer mongoDBContainer = MongoContainers.getDefaultContainer();
5559

5660
@DynamicPropertySource
5761
static void setProperties(DynamicPropertyRegistry registry) {
@@ -60,17 +64,23 @@ static void setProperties(DynamicPropertyRegistry registry) {
6064

6165
@Autowired CustomerRepository repository;
6266
@Autowired MongoOperations operations;
67+
@Autowired StoreRepository storeRepository;
6368

6469
private Customer dave, oliver, carter;
70+
private Store store;
6571

6672
@BeforeEach
6773
void setUp() {
6874

6975
repository.deleteAll();
7076

77+
GeoJsonPolygon polygon = new GeoJsonPolygon(new Point(0.0, 0.0), new Point(0.0, 1.0), new Point(1.0, 1.0), new Point(1.0, 0.0), new Point(0.0, 0.0));
78+
7179
dave = repository.save(new Customer("Dave", "Matthews"));
7280
oliver = repository.save(new Customer("Oliver August", "Matthews"));
7381
carter = repository.save(new Customer("Carter", "Beauford"));
82+
83+
store = storeRepository.save(new Store("store-1", polygon));
7484
}
7585

7686
/**
@@ -146,4 +156,28 @@ void exposesGeoSpatialFunctionality() {
146156
assertThat(distanceToFirstStore.getMetric()).isEqualTo(Metrics.KILOMETERS);
147157
assertThat(distanceToFirstStore.getValue()).isCloseTo(0.862, offset(0.001));
148158
}
159+
160+
/**
161+
* Test case to show the usage of the geospatial operator {@code $geoIntersects}.
162+
*/
163+
@Test
164+
void supportsGeoIntersectsPointInside() {
165+
operations.indexOps(Store.class).createIndex(new GeospatialIndex("serviceArea"));
166+
GeoJsonPoint pointInside = new GeoJsonPoint(0.5, 0.5);
167+
Query pointInsideQuery = Query.query(Criteria.where("serviceArea").intersects(pointInside));
168+
169+
List<Store> stores = operations.find(pointInsideQuery, Store.class);
170+
assertThat(stores).hasSize(1);
171+
assertThat(stores.get(0).getName()).isEqualTo("store-1");
172+
}
173+
174+
@Test
175+
void supportsGeoIntersectsPointOutside() {
176+
operations.indexOps(Store.class).createIndex(new GeospatialIndex("serviceArea"));
177+
GeoJsonPoint pointOutside = new GeoJsonPoint(0.5, 0.5);
178+
Query pointOutsideQuery = Query.query(Criteria.where("serviceArea").intersects(pointOutside));
179+
180+
List<Store> stores = operations.find(pointOutsideQuery, Store.class);
181+
assertThat(stores).isEmpty();
182+
}
149183
}

0 commit comments

Comments
 (0)