Skip to content

Commit 91fe548

Browse files
committed
DATAMONGO-387 - Repository query execution for GeoPage results are now working correctly.
Added special handling of GeoPage return types for repository query methods.
1 parent b6322d7 commit 91fe548

File tree

5 files changed

+91
-47
lines changed

5 files changed

+91
-47
lines changed

spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/AbstractMongoQuery.java

+57-38
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,15 @@
1515
*/
1616
package org.springframework.data.mongodb.repository.query;
1717

18-
import static org.springframework.data.mongodb.repository.query.QueryUtils.applyPagination;
18+
import static org.springframework.data.mongodb.repository.query.QueryUtils.*;
1919

2020
import java.util.List;
2121

2222
import org.springframework.data.domain.PageImpl;
2323
import org.springframework.data.domain.Pageable;
24-
import org.springframework.data.mongodb.core.CollectionCallback;
2524
import org.springframework.data.mongodb.core.MongoOperations;
2625
import org.springframework.data.mongodb.core.geo.Distance;
26+
import org.springframework.data.mongodb.core.geo.GeoPage;
2727
import org.springframework.data.mongodb.core.geo.GeoResult;
2828
import org.springframework.data.mongodb.core.geo.GeoResults;
2929
import org.springframework.data.mongodb.core.geo.Point;
@@ -34,10 +34,6 @@
3434
import org.springframework.data.util.TypeInformation;
3535
import org.springframework.util.Assert;
3636

37-
import com.mongodb.DBCollection;
38-
import com.mongodb.DBCursor;
39-
import com.mongodb.DBObject;
40-
4137
/**
4238
* Base class for {@link RepositoryQuery} implementations for Mongo.
4339
*
@@ -51,8 +47,8 @@ public abstract class AbstractMongoQuery implements RepositoryQuery {
5147
/**
5248
* Creates a new {@link AbstractMongoQuery} from the given {@link MongoQueryMethod} and {@link MongoOperations}.
5349
*
54-
* @param method
55-
* @param template
50+
* @param method must not be {@literal null}.
51+
* @param template must not be {@literal null}.
5652
*/
5753
public AbstractMongoQuery(MongoQueryMethod method, MongoOperations template) {
5854

@@ -63,25 +59,30 @@ public AbstractMongoQuery(MongoQueryMethod method, MongoOperations template) {
6359
this.mongoOperations = template;
6460
}
6561

66-
/* (non-Javadoc)
62+
/*
63+
* (non-Javadoc)
6764
* @see org.springframework.data.repository.query.RepositoryQuery#getQueryMethod()
6865
*/
6966
public MongoQueryMethod getQueryMethod() {
70-
7167
return method;
7268
}
7369

7470
/*
75-
* (non-Javadoc)
76-
*
77-
* @see org.springframework.data.repository.query.RepositoryQuery#execute(java .lang.Object[])
78-
*/
71+
* (non-Javadoc)
72+
* @see org.springframework.data.repository.query.RepositoryQuery#execute(java.lang.Object[])
73+
*/
7974
public Object execute(Object[] parameters) {
8075

8176
MongoParameterAccessor accessor = new MongoParametersParameterAccessor(method, parameters);
8277
Query query = createQuery(new ConvertingParameterAccessor(mongoOperations.getConverter(), accessor));
8378

84-
if (method.isGeoNearQuery()) {
79+
if (method.isGeoNearQuery() && method.isPageQuery()) {
80+
81+
MongoParameterAccessor countAccessor = new MongoParametersParameterAccessor(method, parameters);
82+
Query countQuery = createCountQuery(new ConvertingParameterAccessor(mongoOperations.getConverter(), countAccessor));
83+
84+
return new GeoNearExecution(accessor).execute(query, countQuery);
85+
} else if (method.isGeoNearQuery()) {
8586
return new GeoNearExecution(accessor).execute(query);
8687
} else if (method.isCollectionQuery()) {
8788
return new CollectionExecution().execute(query);
@@ -93,14 +94,25 @@ public Object execute(Object[] parameters) {
9394
}
9495

9596
/**
96-
* Create a {@link Query} instance using the given {@link ParameterAccessor}
97+
* Creates a {@link Query} instance using the given {@link ParameterAccessor}
9798
*
98-
* @param accessor
99-
* @param converter
99+
* @param accessor must not be {@literal null}.
100100
* @return
101101
*/
102102
protected abstract Query createQuery(ConvertingParameterAccessor accessor);
103103

104+
/**
105+
* Creates a {@link Query} instance using the given {@link ConvertingParameterAccessor}. Will delegate to
106+
* {@link #createQuery(ConvertingParameterAccessor)} by default but allows customization of the count query to be
107+
* triggered.
108+
*
109+
* @param accessor must not be {@literal null}.
110+
* @return
111+
*/
112+
protected Query createCountQuery(ConvertingParameterAccessor accessor) {
113+
return createQuery(accessor);
114+
}
115+
104116
private abstract class Execution {
105117

106118
abstract Object execute(Query query);
@@ -122,13 +134,11 @@ protected List<?> readCollection(Query query) {
122134
class CollectionExecution extends Execution {
123135

124136
/*
125-
* (non-Javadoc)
126-
*
127-
* @see org.springframework.data.mongodb.repository.MongoQuery.Execution #execute(com.mongodb.DBObject)
128-
*/
137+
* (non-Javadoc)
138+
* @see org.springframework.data.mongodb.repository.query.AbstractMongoQuery.Execution#execute(org.springframework.data.mongodb.core.query.Query)
139+
*/
129140
@Override
130141
public Object execute(Query query) {
131-
132142
return readCollection(query);
133143
}
134144
}
@@ -162,24 +172,13 @@ public PagedExecution(Pageable pageable) {
162172
Object execute(Query query) {
163173

164174
MongoEntityInformation<?, ?> metadata = method.getEntityInformation();
165-
int count = getCollectionCursor(metadata.getCollectionName(), query.getQueryObject()).count();
175+
long count = mongoOperations.count(query, metadata.getCollectionName());
166176

167177
List<?> result = mongoOperations.find(applyPagination(query, pageable), metadata.getJavaType(),
168178
metadata.getCollectionName());
169179

170180
return new PageImpl(result, pageable, count);
171181
}
172-
173-
private DBCursor getCollectionCursor(String collectionName, final DBObject query) {
174-
175-
return mongoOperations.execute(collectionName, new CollectionCallback<DBCursor>() {
176-
177-
public DBCursor doInCollection(DBCollection collection) {
178-
179-
return collection.find(query);
180-
}
181-
});
182-
}
183182
}
184183

185184
/**
@@ -221,6 +220,28 @@ public GeoNearExecution(MongoParameterAccessor accessor) {
221220
@Override
222221
Object execute(Query query) {
223222

223+
GeoResults<?> results = doExecuteQuery(query);
224+
return isListOfGeoResult() ? results.getContent() : results;
225+
}
226+
227+
/**
228+
* Executes the given {@link Query} to return a page.
229+
*
230+
* @param query must not be {@literal null}.
231+
* @param countQuery must not be {@literal null}.
232+
* @return
233+
*/
234+
Object execute(Query query, Query countQuery) {
235+
236+
MongoEntityInformation<?, ?> information = method.getEntityInformation();
237+
long count = mongoOperations.count(countQuery, information.getCollectionName());
238+
239+
return new GeoPage<Object>(doExecuteQuery(query), accessor.getPageable(), count);
240+
}
241+
242+
@SuppressWarnings("unchecked")
243+
private GeoResults<Object> doExecuteQuery(Query query) {
244+
224245
Point nearLocation = accessor.getGeoNearLocation();
225246
NearQuery nearQuery = NearQuery.near(nearLocation);
226247

@@ -234,10 +255,8 @@ Object execute(Query query) {
234255
}
235256

236257
MongoEntityInformation<?, ?> entityInformation = method.getEntityInformation();
237-
GeoResults<?> results = mongoOperations.geoNear(nearQuery, entityInformation.getJavaType(),
258+
return (GeoResults<Object>) mongoOperations.geoNear(nearQuery, entityInformation.getJavaType(),
238259
entityInformation.getCollectionName());
239-
240-
return isListOfGeoResult() ? results.getContent() : results;
241260
}
242261

243262
private boolean isListOfGeoResult() {

spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoQueryCreator.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,8 @@ private Criteria from(Type type, Criteria criteria, PotentiallyConvertingIterato
203203
case NEAR:
204204

205205
Distance distance = accessor.getMaxDistance();
206-
Point point = nextAs(parameters, Point.class);
206+
Point point = accessor.getGeoNearLocation();
207+
point = point == null ? nextAs(parameters, Point.class) : point;
207208

208209
if (distance == null) {
209210
return criteria.near(point);

spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/PartTreeMongoQuery.java

+16-8
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,8 @@ public class PartTreeMongoQuery extends AbstractMongoQuery {
3838
/**
3939
* Creates a new {@link PartTreeMongoQuery} from the given {@link QueryMethod} and {@link MongoTemplate}.
4040
*
41-
* @param method
42-
* @param template
41+
* @param method must not be {@literal null}.
42+
* @param template must not be {@literal null}.
4343
*/
4444
public PartTreeMongoQuery(MongoQueryMethod method, MongoOperations mongoOperations) {
4545

@@ -50,23 +50,31 @@ public PartTreeMongoQuery(MongoQueryMethod method, MongoOperations mongoOperatio
5050
}
5151

5252
/**
53+
* Return the {@link PartTree} backing the query.
54+
*
5355
* @return the tree
5456
*/
5557
public PartTree getTree() {
5658
return tree;
5759
}
5860

5961
/*
60-
* (non-Javadoc)
61-
*
62-
* @see
63-
* org.springframework.data.mongodb.repository.AbstractMongoQuery#createQuery(org.springframework.data.
64-
* document.mongodb.repository.ConvertingParameterAccessor)
65-
*/
62+
* (non-Javadoc)
63+
* @see org.springframework.data.mongodb.repository.query.AbstractMongoQuery#createQuery(org.springframework.data.mongodb.repository.query.ConvertingParameterAccessor, boolean)
64+
*/
6665
@Override
6766
protected Query createQuery(ConvertingParameterAccessor accessor) {
6867

6968
MongoQueryCreator creator = new MongoQueryCreator(tree, accessor, context, isGeoNearQuery);
7069
return creator.createQuery();
7170
}
71+
72+
/*
73+
* (non-Javadoc)
74+
* @see org.springframework.data.mongodb.repository.query.AbstractMongoQuery#createCountQuery(org.springframework.data.mongodb.repository.query.ConvertingParameterAccessor)
75+
*/
76+
@Override
77+
protected Query createCountQuery(ConvertingParameterAccessor accessor) {
78+
return new MongoQueryCreator(tree, accessor, context, false).createQuery();
79+
}
7280
}

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

+13
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
import org.springframework.data.mongodb.core.geo.Box;
3636
import org.springframework.data.mongodb.core.geo.Circle;
3737
import org.springframework.data.mongodb.core.geo.Distance;
38+
import org.springframework.data.mongodb.core.geo.GeoPage;
3839
import org.springframework.data.mongodb.core.geo.GeoResults;
3940
import org.springframework.data.mongodb.core.geo.Metrics;
4041
import org.springframework.data.mongodb.core.geo.Point;
@@ -366,6 +367,18 @@ public void executesGeoNearQueryForResultsCorrectly() {
366367
assertThat(results.getContent().isEmpty(), is(false));
367368
}
368369

370+
@Test
371+
public void executesGeoPageQueryForResultsCorrectly() {
372+
373+
Point point = new Point(-73.99171, 40.738868);
374+
dave.setLocation(point);
375+
repository.save(dave);
376+
377+
GeoPage<Person> results = repository.findByLocationNear(new Point(-73.99, 40.73), new Distance(2000,
378+
Metrics.KILOMETERS), new PageRequest(0, 20));
379+
assertThat(results.getContent().isEmpty(), is(false));
380+
}
381+
369382
/**
370383
* @see DATAMONGO-323
371384
*/

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

+3
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import org.springframework.data.mongodb.core.geo.Box;
2525
import org.springframework.data.mongodb.core.geo.Circle;
2626
import org.springframework.data.mongodb.core.geo.Distance;
27+
import org.springframework.data.mongodb.core.geo.GeoPage;
2728
import org.springframework.data.mongodb.core.geo.GeoResults;
2829
import org.springframework.data.mongodb.core.geo.Point;
2930
import org.springframework.data.mongodb.core.geo.Polygon;
@@ -148,4 +149,6 @@ public interface PersonRepository extends MongoRepository<Person, String>, Query
148149
List<Person> findByNamedQuery(String firstname);
149150

150151
GeoResults<Person> findByLocationNear(Point point, Distance maxDistance);
152+
153+
GeoPage<Person> findByLocationNear(Point point, Distance maxDistance, Pageable pageable);
151154
}

0 commit comments

Comments
 (0)