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.

Original pull request: #261.
  • Loading branch information
Thomas Darimont committed Jan 20, 2015
1 parent a530bc8 commit 00d3da7
Show file tree
Hide file tree
Showing 5 changed files with 30 additions and 45 deletions.
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2014 the original author or authors.
* Copyright 2013-2015 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 @@ -293,14 +293,16 @@ public static Fields bind(String name, String target) {
}

/**
* Creates a new {@link GeoNearOperation} instance from the given {@link NearQuery}.
* Creates a new {@link GeoNearOperation} instance from the given {@link NearQuery} and the distanceField. The
* {@code distanceField} defines output field that contains the calculated distance.
*
* @param query
* @param query must not be {@literal null}.
* @param distanceField must not be {@literal null} or empty.
* @return
* @since 1.7
*/
public static GeoNearOperation geoNear(NearQuery query) {
return new GeoNearOperation(query);
public static GeoNearOperation geoNear(NearQuery query, String distanceField) {
return new GeoNearOperation(query, distanceField);
}

/**
Expand Down
@@ -1,5 +1,5 @@
/*
* Copyright 2013 the original author or authors.
* Copyright 2013-2015 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,15 @@
public class GeoNearOperation implements AggregationOperation {

private final NearQuery nearQuery;
private final String distanceField;

public GeoNearOperation(NearQuery nearQuery) {
public GeoNearOperation(NearQuery nearQuery, String distanceField) {

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

this.nearQuery = nearQuery;
this.distanceField = distanceField;
}

/*
Expand All @@ -43,6 +45,10 @@ public GeoNearOperation(NearQuery nearQuery) {
*/
@Override
public DBObject toDBObject(AggregationOperationContext context) {
return new BasicDBObject("$geoNear", context.getMappedObject(nearQuery.toDBObject()));

BasicDBObject command = (BasicDBObject) context.getMappedObject(nearQuery.toDBObject());
command.put("distanceField", distanceField);

return new BasicDBObject("$geoNear", command);
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2011-2014 the original author or authors.
* Copyright 2011-2015 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 @@ -44,7 +44,6 @@ 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 @@ -158,21 +157,6 @@ 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 @@ -354,13 +338,6 @@ 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 @@ -390,10 +367,6 @@ public DBObject toDBObject() {

dbObject.put("spherical", spherical);

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

return dbObject;
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2013 the original author or authors.
* Copyright 2013-2015 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 @@ -1035,17 +1035,18 @@ public void shouldSupportGeoNearQueriesForAggregation() {

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

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

Aggregation agg = newAggregation(Aggregation.geoNear(geoNear));
Aggregation agg = newAggregation(Aggregation.geoNear(geoNear, "distance"));
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));

mongoTemplate.dropCollection(Venue.class);
}

private void assertLikeStats(LikeStats like, String id, long count) {
Expand Down
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2014 the original author or authors.
* Copyright 2013-2015 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 All @@ -22,6 +22,7 @@
import org.springframework.data.mongodb.core.DBObjectTestUtils;
import org.springframework.data.mongodb.core.query.NearQuery;

import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;

/**
Expand All @@ -38,11 +39,13 @@ public class GeoNearOperationUnitTests {
@Test
public void rendersNearQueryAsAggregationOperation() {

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

DBObject nearClause = DBObjectTestUtils.getAsDBObject(dbObject, "$geoNear");
assertThat(nearClause, is(query.toDBObject()));

DBObject expected = (DBObject) new BasicDBObject(query.toDBObject().toMap()).append("distanceField", "distance");
assertThat(nearClause, is(expected));
}
}

0 comments on commit 00d3da7

Please sign in to comment.