diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/Aggregation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/Aggregation.java index a9cf635350..870c59344e 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/Aggregation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/Aggregation.java @@ -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. @@ -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; @@ -291,6 +292,19 @@ 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} and the{@code distanceField}. The + * {@code distanceField} defines output field that contains the calculated distance. + * + * @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, String distanceField) { + return new GeoNearOperation(query, distanceField); + } + /** * Returns a new {@link AggregationOptions.Builder}. * diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/GeoNearOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/GeoNearOperation.java index d30a73727b..29afc03f8e 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/GeoNearOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/GeoNearOperation.java @@ -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. @@ -22,17 +22,33 @@ import com.mongodb.DBObject; /** + * Represents a {@code geoNear} aggregation operation. + *

+ * We recommend to use the static factory method {@link Aggregation#geoNear(NearQuery, String)} instead of creating + * instances of this class directly. + * * @author Thomas Darimont * @since 1.3 */ public class GeoNearOperation implements AggregationOperation { private final NearQuery nearQuery; + private final String distanceField; - public GeoNearOperation(NearQuery nearQuery) { + /** + * Creates a new {@link GeoNearOperation} from the given {@link NearQuery} and the given distance field. The + * {@code distanceField} defines output field that contains the calculated distance. + * + * @param query must not be {@literal null}. + * @param distanceField must not be {@literal null}. + */ + public GeoNearOperation(NearQuery nearQuery, String distanceField) { + + Assert.notNull(nearQuery, "NearQuery must not be null."); + Assert.hasLength(distanceField, "Distance field must not be null or empty."); - Assert.notNull(nearQuery); this.nearQuery = nearQuery; + this.distanceField = distanceField; } /* @@ -41,6 +57,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); } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/GroupOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/GroupOperation.java index 11d285ec73..02efbdc2d2 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/GroupOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/GroupOperation.java @@ -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. @@ -31,6 +31,9 @@ /** * Encapsulates the aggregation framework {@code $group}-operation. + *

+ * We recommend to use the static factory method {@link Aggregation#group(Fields)} instead of creating instances of this + * class directly. * * @see http://docs.mongodb.org/manual/reference/aggregation/group/#stage._S_group * @author Sebastian Herold diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/LimitOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/LimitOperation.java index 22614dfb58..b56a59e01d 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/LimitOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/LimitOperation.java @@ -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. @@ -21,7 +21,10 @@ import com.mongodb.DBObject; /** - * Encapsulates the {@code $limit}-operation + * Encapsulates the {@code $limit}-operation. + *

+ * We recommend to use the static factory method {@link Aggregation#limit(long)} instead of creating instances of this + * class directly. * * @see http://docs.mongodb.org/manual/reference/aggregation/limit/ * @author Thomas Darimont diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/MatchOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/MatchOperation.java index 6d5669aa7b..eb86fb1e5c 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/MatchOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/MatchOperation.java @@ -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. @@ -22,7 +22,11 @@ import com.mongodb.DBObject; /** - * Encapsulates the {@code $match}-operation + * Encapsulates the {@code $match}-operation. + *

+ * We recommend to use the static factory method + * {@link Aggregation#match(org.springframework.data.mongodb.core.query.Criteria)} instead of creating instances of this + * class directly. * * @see http://docs.mongodb.org/manual/reference/aggregation/match/ * @author Sebastian Herold diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ProjectionOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ProjectionOperation.java index 5212fc1d75..1b7cc323f4 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ProjectionOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/ProjectionOperation.java @@ -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. @@ -28,10 +28,13 @@ import com.mongodb.DBObject; /** - * Encapsulates the aggregation framework {@code $project}-operation. Projection of field to be used in an - * {@link Aggregation}. A projection is similar to a {@link Field} inclusion/exclusion but more powerful. It can - * generate new fields, change values of given field etc. + * Encapsulates the aggregation framework {@code $project}-operation. *

+ * Projection of field to be used in an {@link Aggregation}. A projection is similar to a {@link Field} + * inclusion/exclusion but more powerful. It can generate new fields, change values of given field etc. + *

+ * We recommend to use the static factory method {@link Aggregation#project(Fields)} instead of creating instances of + * this class directly. * * @see http://docs.mongodb.org/manual/reference/aggregation/project/ * @author Tobias Trelle diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SkipOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SkipOperation.java index 99c2dda20c..67d598134e 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SkipOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SkipOperation.java @@ -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. @@ -22,6 +22,9 @@ /** * Encapsulates the aggregation framework {@code $skip}-operation. + *

+ * We recommend to use the static factory method {@link Aggregation#skip(int)} instead of creating instances of this + * class directly. * * @see http://docs.mongodb.org/manual/reference/aggregation/skip/ * @author Thomas Darimont diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SortOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SortOperation.java index b405c4309b..0b6f6dee2e 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SortOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/SortOperation.java @@ -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. @@ -26,6 +26,9 @@ /** * Encapsulates the aggregation framework {@code $sort}-operation. + *

+ * We recommend to use the static factory method {@link Aggregation#sort(Direction, String...)} instead of creating + * instances of this class directly. * * @see http://docs.mongodb.org/manual/reference/aggregation/sort/#pipe._S_sort * @author Thomas Darimont diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/UnwindOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/UnwindOperation.java index 5410f79f32..883cb8a8c4 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/UnwindOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/UnwindOperation.java @@ -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. @@ -23,6 +23,9 @@ /** * Encapsulates the aggregation framework {@code $unwind}-operation. + *

+ * We recommend to use the static factory method {@link Aggregation#unwind(String)} instead of creating instances of + * this class directly. * * @see http://docs.mongodb.org/manual/reference/aggregation/unwind/#pipe._S_unwind * @author Thomas Darimont diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/AggregationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/AggregationTests.java index cc5be660fc..8c448543ce 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/AggregationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/AggregationTests.java @@ -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. @@ -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; @@ -120,6 +123,7 @@ private void cleanDb() { mongoTemplate.dropCollection(User.class); mongoTemplate.dropCollection(Person.class); mongoTemplate.dropCollection(Reservation.class); + mongoTemplate.dropCollection(Venue.class); } /** @@ -1018,6 +1022,30 @@ public void shouldRetrieveDateTimeFragementsCorrectly() throws Exception { assertThat(dbo.get("dayOfYearPlus1DayManually"), is((Object) dateTime.plusDays(1).getDayOfYear())); } + /** + * @see DATAMONGO-1127 + */ + @Test + public void shouldSupportGeoNearQueriesForAggregationWithDistanceField() { + + 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); + + Aggregation agg = newAggregation(Aggregation.geoNear(geoNear, "distance")); + AggregationResults 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())); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/GeoNearOperationUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/GeoNearOperationUnitTests.java index 16d4e145c6..95e2f13a73 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/GeoNearOperationUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/GeoNearOperationUnitTests.java @@ -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. @@ -22,23 +22,30 @@ import org.springframework.data.mongodb.core.DBObjectTestUtils; import org.springframework.data.mongodb.core.query.NearQuery; +import com.mongodb.BasicDBObject; import com.mongodb.DBObject; /** * 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); - GeoNearOperation operation = new GeoNearOperation(query); + 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)); } }