Skip to content

Commit

Permalink
DATAMONGO-1127 - Add support for geoNear queries with distance inform…
Browse files Browse the repository at this point in the history
…ation.

We now support geoNear queries in Aggregations. Exposed GeoNearOperation factory method in Aggregation. Introduced new distanceField property to NearQuery since it is required for geoNear queries in Aggregations.

Original pull request: #261.
  • Loading branch information
Thomas Darimont committed Dec 29, 2014
1 parent b5b4f87 commit 505d15b
Show file tree
Hide file tree
Showing 5 changed files with 78 additions and 3 deletions.
Expand Up @@ -27,6 +27,7 @@
import org.springframework.data.mongodb.core.aggregation.ExposedFields.FieldReference;
import org.springframework.data.mongodb.core.aggregation.Fields.AggregationField;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.NearQuery;
import org.springframework.data.mongodb.core.query.SerializationUtils;
import org.springframework.util.Assert;

Expand Down Expand Up @@ -291,6 +292,17 @@ public static Fields bind(String name, String target) {
return Fields.from(field(name, target));
}

/**
* Creates a new {@link GeoNearOperation} instance from the given {@link NearQuery}.
*
* @param query
* @return
* @since 1.7
*/
public static GeoNearOperation geoNear(NearQuery query) {
return new GeoNearOperation(query);
}

/**
* Returns a new {@link AggregationOptions.Builder}.
*
Expand Down
Expand Up @@ -32,6 +32,8 @@ public class GeoNearOperation implements AggregationOperation {
public GeoNearOperation(NearQuery nearQuery) {

Assert.notNull(nearQuery);
Assert.notNull(nearQuery.getDistanceField(), "distanceField must be configured in NearQuery.");

this.nearQuery = nearQuery;
}

Expand Down
Expand Up @@ -44,6 +44,7 @@ public final class NearQuery {
private boolean spherical;
private Integer num;
private Integer skip;
private String distanceField;

/**
* Creates a new {@link NearQuery}.
Expand Down Expand Up @@ -157,6 +158,21 @@ public NearQuery with(Pageable pageable) {
return this;
}

/**
* Configures the name of the distanceField.
*
* @param distanceField
* @return
*/
public NearQuery withDistanceField(String distanceField) {

Assert.hasText(distanceField, "distanceField must not be empty.");

this.distanceField = distanceField;

return this;
}

/**
* Sets the max distance results shall have from the configured origin. If a {@link Metric} was set before the given
* value will be interpreted as being a value in that metric. E.g.
Expand Down Expand Up @@ -338,6 +354,13 @@ public Integer getSkip() {
return skip;
}

/**
* @return the name of the distanceField.
*/
public String getDistanceField() {
return distanceField;
}

/**
* Returns the {@link DBObject} built by the {@link NearQuery}.
*
Expand Down Expand Up @@ -367,6 +390,10 @@ public DBObject toDBObject() {

dbObject.put("spherical", spherical);

if (distanceField != null) {
dbObject.put("distanceField", distanceField);
}

return dbObject;
}
}
Expand Up @@ -47,11 +47,14 @@
import org.springframework.dao.DataAccessException;
import org.springframework.data.annotation.Id;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.geo.Metrics;
import org.springframework.data.mapping.model.MappingException;
import org.springframework.data.mongodb.core.CollectionCallback;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.Venue;
import org.springframework.data.mongodb.core.aggregation.AggregationTests.CarDescriptor.Entry;
import org.springframework.data.mongodb.core.mapping.Document;
import org.springframework.data.mongodb.core.index.GeospatialIndex;
import org.springframework.data.mongodb.core.query.NearQuery;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.repository.Person;
import org.springframework.data.util.Version;
Expand Down Expand Up @@ -1018,6 +1021,33 @@ public void shouldRetrieveDateTimeFragementsCorrectly() throws Exception {
assertThat(dbo.get("dayOfYearPlus1DayManually"), is((Object) dateTime.plusDays(1).getDayOfYear()));
}

/**
* @see DATAMONGO-1127
*/
@Test
public void shouldSupportGeoNearQueriesForAggregation() {

mongoTemplate.dropCollection(Venue.class);

mongoTemplate.insert(new Venue("Penn Station", -73.99408, 40.75057));
mongoTemplate.insert(new Venue("10gen Office", -73.99171, 40.738868));
mongoTemplate.insert(new Venue("Flatiron Building", -73.988135, 40.741404));

mongoTemplate.indexOps(Venue.class).ensureIndex(new GeospatialIndex("location"));

NearQuery geoNear = NearQuery.near(-73, 40, Metrics.KILOMETERS).num(10).maxDistance(150)
.withDistanceField("distance");

Aggregation agg = newAggregation(Aggregation.geoNear(geoNear));
AggregationResults<DBObject> result = mongoTemplate.aggregate(agg, Venue.class, DBObject.class);

assertThat(result.getMappedResults(), hasSize(3));

DBObject firstResult = result.getMappedResults().get(0);
assertThat(firstResult.containsField("distance"), is(true));
assertThat(firstResult.get("distance"), is((Object) 117.620092203928));
}

private void assertLikeStats(LikeStats like, String id, long count) {

assertThat(like, is(notNullValue()));
Expand Down
@@ -1,5 +1,5 @@
/*
* Copyright 2013 the original author or authors.
* Copyright 2013-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -28,13 +28,17 @@
* Unit tests for {@link GeoNearOperation}.
*
* @author Oliver Gierke
* @author Thomas Darimont
*/
public class GeoNearOperationUnitTests {

/**
* @see DATAMONGO-1127
*/
@Test
public void rendersNearQueryAsAggregationOperation() {

NearQuery query = NearQuery.near(10.0, 10.0);
NearQuery query = NearQuery.near(10.0, 10.0).withDistanceField("distance");
GeoNearOperation operation = new GeoNearOperation(query);
DBObject dbObject = operation.toDBObject(Aggregation.DEFAULT_CONTEXT);

Expand Down

0 comments on commit 505d15b

Please sign in to comment.