Browse Source

DATAMONGO-1136 - Use $geoWithin instead of $within for geo queries.

We now use the $geoWithin operator for geospatial criteria which requires to run on  at least MongoDB 2.4.

Original pull request: #263.
pull/265/head
Christoph Strobl 11 years ago committed by Oliver Gierke
parent
commit
59e54cecd2
  1. 12
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Criteria.java
  2. 41
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/GeoCommand.java
  3. 392
      spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/geo/AbstractGeoSpatialTests.java
  4. 68
      spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/geo/GeoSpatial2DSphereTests.java
  5. 82
      spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/geo/GeoSpatial2DTests.java
  6. 30
      spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/MongoQueryCreatorUnitTests.java
  7. 2
      src/main/asciidoc/preface.adoc
  8. 4
      src/main/asciidoc/reference/mongo-repositories.adoc
  9. 14
      src/main/asciidoc/reference/mongodb.adoc

12
spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Criteria.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2010-2014 the original author or authors.
* Copyright 2010-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.
@ -376,8 +376,8 @@ public class Criteria implements CriteriaDefinition { @@ -376,8 +376,8 @@ public class Criteria implements CriteriaDefinition {
}
/**
* Creates a geospatial criterion using a {@literal $within $centerSphere} operation. This is only available for Mongo
* 1.7 and higher.
* Creates a geospatial criterion using a {@literal $geoWithin $centerSphere} operation. This is only available for
* Mongo 2.4 and higher.
*
* @see http://docs.mongodb.org/manual/reference/operator/query/geoWithin/
* @see http://docs.mongodb.org/manual/reference/operator/query/centerSphere/
@ -386,12 +386,12 @@ public class Criteria implements CriteriaDefinition { @@ -386,12 +386,12 @@ public class Criteria implements CriteriaDefinition {
*/
public Criteria withinSphere(Circle circle) {
Assert.notNull(circle);
criteria.put("$within", new GeoCommand(new Sphere(circle)));
criteria.put("$geoWithin", new GeoCommand(new Sphere(circle)));
return this;
}
/**
* Creates a geospatial criterion using a {@literal $within} operation.
* Creates a geospatial criterion using a {@literal $geoWithin} operation.
*
* @see http://docs.mongodb.org/manual/reference/operator/query/geoWithin/
* @param shape
@ -400,7 +400,7 @@ public class Criteria implements CriteriaDefinition { @@ -400,7 +400,7 @@ public class Criteria implements CriteriaDefinition {
public Criteria within(Shape shape) {
Assert.notNull(shape);
criteria.put("$within", new GeoCommand(shape));
criteria.put("$geoWithin", new GeoCommand(shape));
return this;
}

41
spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/GeoCommand.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2014 the original author or authors.
* Copyright 2014-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,11 +21,13 @@ import org.springframework.data.geo.Polygon; @@ -21,11 +21,13 @@ import org.springframework.data.geo.Polygon;
import org.springframework.data.geo.Shape;
import org.springframework.data.mongodb.core.geo.Sphere;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
/**
* Wrapper around a {@link Shape} to allow appropriate query rendering.
*
* @author Thomas Darimont
* @author Christoph Strobl
* @since 1.5
*/
public class GeoCommand {
@ -82,4 +84,41 @@ public class GeoCommand { @@ -82,4 +84,41 @@ public class GeoCommand {
throw new IllegalArgumentException("Unknown shape: " + shape);
}
/*
* (non-Javadoc)
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
int result = 0;
result += ObjectUtils.nullSafeHashCode(this.command);
result += ObjectUtils.nullSafeHashCode(this.shape);
return result;
}
/*
* (non-Javadoc)
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (!(obj instanceof GeoCommand)) {
return false;
}
GeoCommand that = (GeoCommand) obj;
if (!ObjectUtils.nullSafeEquals(this.command, that.command)) {
return false;
}
return ObjectUtils.nullSafeEquals(this.shape, that.shape);
}
}

392
spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/geo/GeoSpatialTests.java → spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/geo/AbstractGeoSpatialTests.java

@ -1,216 +1,176 @@ @@ -1,216 +1,176 @@
/*
* Copyright 2010-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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.mongodb.core.geo;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import static org.springframework.data.mongodb.core.query.Criteria.*;
import static org.springframework.data.mongodb.core.query.Query.*;
import java.util.Collection;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.junit.Before;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.geo.Box;
import org.springframework.data.geo.Circle;
import org.springframework.data.geo.GeoResults;
import org.springframework.data.geo.Metric;
import org.springframework.data.geo.Metrics;
import org.springframework.data.geo.Point;
import org.springframework.data.geo.Polygon;
import org.springframework.data.mongodb.config.AbstractIntegrationTests;
import org.springframework.data.mongodb.core.CollectionCallback;
import org.springframework.data.mongodb.core.IndexOperations;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.Venue;
import org.springframework.data.mongodb.core.index.GeospatialIndex;
import org.springframework.data.mongodb.core.index.IndexField;
import org.springframework.data.mongodb.core.index.IndexInfo;
import org.springframework.data.mongodb.core.query.NearQuery;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import com.mongodb.DBCollection;
import com.mongodb.DBObject;
import com.mongodb.MongoException;
import com.mongodb.WriteConcern;
/**
* Modified from https://github.com/deftlabs/mongo-java-geospatial-example
*
* @author Mark Pollack
* @author Oliver Gierke
* @author Thomas Darimont
*/
public class GeoSpatialTests extends AbstractIntegrationTests {
private static final Log LOGGER = LogFactory.getLog(GeoSpatialTests.class);
@Autowired MongoTemplate template;
ExpressionParser parser = new SpelExpressionParser();
@Before
public void setUp() throws Exception {
template.setWriteConcern(WriteConcern.FSYNC_SAFE);
template.indexOps(Venue.class).ensureIndex(new GeospatialIndex("location"));
indexCreated();
addVenues();
}
private void addVenues() {
template.insert(new Venue("Penn Station", -73.99408, 40.75057));
template.insert(new Venue("10gen Office", -73.99171, 40.738868));
template.insert(new Venue("Flatiron Building", -73.988135, 40.741404));
template.insert(new Venue("Players Club", -73.997812, 40.739128));
template.insert(new Venue("City Bakery ", -73.992491, 40.738673));
template.insert(new Venue("Splash Bar", -73.992491, 40.738673));
template.insert(new Venue("Momofuku Milk Bar", -73.985839, 40.731698));
template.insert(new Venue("Shake Shack", -73.98820, 40.74164));
template.insert(new Venue("Penn Station", -73.99408, 40.75057));
template.insert(new Venue("Empire State Building", -73.98602, 40.74894));
// template.insert(new Venue("Washington Square Park", -73.99756, 40.73083));
template.insert(new Venue("Ulaanbaatar, Mongolia", 106.9154, 47.9245));
template.insert(new Venue("Maplewood, NJ", -74.2713, 40.73137));
}
@Test
public void geoNear() {
NearQuery geoNear = NearQuery.near(-73, 40, Metrics.KILOMETERS).num(10).maxDistance(150);
GeoResults<Venue> result = template.geoNear(geoNear, Venue.class);
assertThat(result.getContent().size(), is(not(0)));
assertThat(result.getAverageDistance().getMetric(), is((Metric) Metrics.KILOMETERS));
}
@Test
public void withinCenter() {
Circle circle = new Circle(-73.99171, 40.738868, 0.01);
List<Venue> venues = template.find(query(where("location").within(circle)), Venue.class);
assertThat(venues.size(), is(7));
}
@Test
public void withinCenterSphere() {
Circle circle = new Circle(-73.99171, 40.738868, 0.003712240453784);
List<Venue> venues = template.find(query(where("location").withinSphere(circle)), Venue.class);
assertThat(venues.size(), is(11));
}
@Test
public void withinBox() {
Box box = new Box(new Point(-73.99756, 40.73083), new Point(-73.988135, 40.741404));
List<Venue> venues = template.find(query(where("location").within(box)), Venue.class);
assertThat(venues.size(), is(4));
}
@Test
public void withinPolygon() {
Point first = new Point(-73.99756, 40.73083);
Point second = new Point(-73.99756, 40.741404);
Point third = new Point(-73.988135, 40.741404);
Point fourth = new Point(-73.988135, 40.73083);
Polygon polygon = new Polygon(first, second, third, fourth);
List<Venue> venues = template.find(query(where("location").within(polygon)), Venue.class);
assertThat(venues.size(), is(4));
}
@Test
public void nearPoint() {
Point point = new Point(-73.99171, 40.738868);
List<Venue> venues = template.find(query(where("location").near(point).maxDistance(0.01)), Venue.class);
assertThat(venues.size(), is(7));
}
@Test
public void nearSphere() {
Point point = new Point(-73.99171, 40.738868);
Query query = query(where("location").nearSphere(point).maxDistance(0.003712240453784));
List<Venue> venues = template.find(query, Venue.class);
assertThat(venues.size(), is(11));
}
@Test
public void searchAllData() {
Venue foundVenue = template.findOne(query(where("name").is("Penn Station")), Venue.class);
assertThat(foundVenue, is(notNullValue()));
List<Venue> venues = template.findAll(Venue.class);
assertThat(venues.size(), is(12));
Collection<?> names = (Collection<?>) parser.parseExpression("![name]").getValue(venues);
assertThat(names.size(), is(12));
}
public void indexCreated() {
List<DBObject> indexInfo = getIndexInfo(Venue.class);
LOGGER.debug(indexInfo);
assertThat(indexInfo.size(), is(2));
assertThat(indexInfo.get(1).get("name").toString(), is("location_2d"));
assertThat(indexInfo.get(1).get("ns").toString(), is("database.newyork"));
}
/**
* @see DATAMONGO-360
*/
@Test
public void indexInfoIsCorrect() {
IndexOperations operations = template.indexOps(Venue.class);
List<IndexInfo> indexInfo = operations.getIndexInfo();
assertThat(indexInfo.size(), is(2));
List<IndexField> fields = indexInfo.get(0).getIndexFields();
assertThat(fields.size(), is(1));
assertThat(fields, hasItem(IndexField.create("_id", Direction.ASC)));
fields = indexInfo.get(1).getIndexFields();
assertThat(fields.size(), is(1));
assertThat(fields, hasItem(IndexField.geo("location")));
}
// TODO move to MongoAdmin
public List<DBObject> getIndexInfo(Class<?> clazz) {
return template.execute(clazz, new CollectionCallback<List<DBObject>>() {
public List<DBObject> doInCollection(DBCollection collection) throws MongoException, DataAccessException {
return collection.getIndexInfo();
}
});
}
}
/*
* Copyright 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.mongodb.core.geo;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import static org.springframework.data.mongodb.core.query.Criteria.*;
import static org.springframework.data.mongodb.core.query.Query.*;
import java.util.List;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.geo.Box;
import org.springframework.data.geo.Circle;
import org.springframework.data.geo.GeoResults;
import org.springframework.data.geo.Metric;
import org.springframework.data.geo.Metrics;
import org.springframework.data.geo.Point;
import org.springframework.data.geo.Polygon;
import org.springframework.data.mongodb.config.AbstractMongoConfiguration;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.Venue;
import org.springframework.data.mongodb.core.query.NearQuery;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.mongodb.Mongo;
import com.mongodb.MongoClient;
import com.mongodb.WriteConcern;
/**
* @author Christoph Strobl
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
public abstract class AbstractGeoSpatialTests {
@Configuration
static class TestConfig extends AbstractMongoConfiguration {
@Override
protected String getDatabaseName() {
return "database";
}
@Override
public Mongo mongo() throws Exception {
return new MongoClient();
}
}
@Autowired MongoTemplate template;
@Before
public void setUp() {
template.setWriteConcern(WriteConcern.FSYNC_SAFE);
createIndex();
addVenues();
}
@After
public void tearDown() {
dropIndex();
removeVenues();
}
/**
* Create the index required to run the tests.
*/
protected abstract void createIndex();
/**
* Remove index
*/
protected abstract void dropIndex();
protected void removeVenues() {
template.dropCollection(Venue.class);
}
protected void addVenues() {
template.insert(new Venue("Penn Station", -73.99408, 40.75057));
template.insert(new Venue("10gen Office", -73.99171, 40.738868));
template.insert(new Venue("Flatiron Building", -73.988135, 40.741404));
template.insert(new Venue("Players Club", -73.997812, 40.739128));
template.insert(new Venue("City Bakery ", -73.992491, 40.738673));
template.insert(new Venue("Splash Bar", -73.992491, 40.738673));
template.insert(new Venue("Momofuku Milk Bar", -73.985839, 40.731698));
template.insert(new Venue("Shake Shack", -73.98820, 40.74164));
template.insert(new Venue("Penn Station", -73.99408, 40.75057));
template.insert(new Venue("Empire State Building", -73.98602, 40.74894));
template.insert(new Venue("Ulaanbaatar, Mongolia", 106.9154, 47.9245));
template.insert(new Venue("Maplewood, NJ", -74.2713, 40.73137));
}
@Test
public void geoNear() {
NearQuery geoNear = NearQuery.near(-73, 40, Metrics.KILOMETERS).num(10).maxDistance(150);
GeoResults<Venue> result = template.geoNear(geoNear, Venue.class);
assertThat(result.getContent().size(), is(not(0)));
assertThat(result.getAverageDistance().getMetric(), is((Metric) Metrics.KILOMETERS));
}
@Test
public void withinCenter() {
Circle circle = new Circle(-73.99171, 40.738868, 0.01);
List<Venue> venues = template.find(query(where("location").within(circle)), Venue.class);
assertThat(venues.size(), is(7));
}
@Test
public void withinCenterSphere() {
Circle circle = new Circle(-73.99171, 40.738868, 0.003712240453784);
List<Venue> venues = template.find(query(where("location").withinSphere(circle)), Venue.class);
assertThat(venues.size(), is(11));
}
@Test
public void withinBox() {
Box box = new Box(new Point(-73.99756, 40.73083), new Point(-73.988135, 40.741404));
List<Venue> venues = template.find(query(where("location").within(box)), Venue.class);
assertThat(venues.size(), is(4));
}
@Test
public void withinPolygon() {
Point first = new Point(-73.99756, 40.73083);
Point second = new Point(-73.99756, 40.741404);
Point third = new Point(-73.988135, 40.741404);
Point fourth = new Point(-73.988135, 40.73083);
Polygon polygon = new Polygon(first, second, third, fourth);
List<Venue> venues = template.find(query(where("location").within(polygon)), Venue.class);
assertThat(venues.size(), is(4));
}
@Test
public void nearSphere() {
Point point = new Point(-73.99171, 40.738868);
Query query = query(where("location").nearSphere(point).maxDistance(0.003712240453784));
List<Venue> venues = template.find(query, Venue.class);
assertThat(venues.size(), is(11));
}
}

68
spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/geo/GeoSpatial2DSphereTests.java

@ -0,0 +1,68 @@ @@ -0,0 +1,68 @@
/*
* Copyright 2010-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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.mongodb.core.geo;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import java.util.List;
import org.junit.Test;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.mongodb.core.IndexOperations;
import org.springframework.data.mongodb.core.Venue;
import org.springframework.data.mongodb.core.index.GeoSpatialIndexType;
import org.springframework.data.mongodb.core.index.GeospatialIndex;
import org.springframework.data.mongodb.core.index.IndexField;
import org.springframework.data.mongodb.core.index.IndexInfo;
/**
* @author Christoph Strobl
*/
public class GeoSpatial2DSphereTests extends AbstractGeoSpatialTests {
/**
* @see DATAMONGO-360
*/
@Test
public void indexInfoIsCorrect() {
IndexOperations operations = template.indexOps(Venue.class);
List<IndexInfo> indexInfo = operations.getIndexInfo();
assertThat(indexInfo.size(), is(2));
List<IndexField> fields = indexInfo.get(0).getIndexFields();
assertThat(fields.size(), is(1));
assertThat(fields, hasItem(IndexField.create("_id", Direction.ASC)));
fields = indexInfo.get(1).getIndexFields();
assertThat(fields.size(), is(1));
assertThat(fields, hasItem(IndexField.geo("location")));
}
@Override
protected void createIndex() {
template.indexOps(Venue.class).ensureIndex(new GeospatialIndex("location").typed(GeoSpatialIndexType.GEO_2DSPHERE));
}
@Override
protected void dropIndex() {
template.indexOps(Venue.class).dropIndex("location_2dsphere");
}
}

82
spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/geo/GeoSpatial2DTests.java

@ -0,0 +1,82 @@ @@ -0,0 +1,82 @@
/*
* Copyright 2010-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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.mongodb.core.geo;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import static org.springframework.data.mongodb.core.query.Criteria.*;
import static org.springframework.data.mongodb.core.query.Query.*;
import java.util.List;
import org.junit.Test;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.geo.Point;
import org.springframework.data.mongodb.core.IndexOperations;
import org.springframework.data.mongodb.core.Venue;
import org.springframework.data.mongodb.core.index.GeoSpatialIndexType;
import org.springframework.data.mongodb.core.index.GeospatialIndex;
import org.springframework.data.mongodb.core.index.IndexField;
import org.springframework.data.mongodb.core.index.IndexInfo;
/**
* Modified from https://github.com/deftlabs/mongo-java-geospatial-example
*
* @author Mark Pollack
* @author Oliver Gierke
* @author Thomas Darimont
* @author Christoph Strobl
*/
public class GeoSpatial2DTests extends AbstractGeoSpatialTests {
@Test
public void nearPoint() {
Point point = new Point(-73.99171, 40.738868);
List<Venue> venues = template.find(query(where("location").near(point).maxDistance(0.01)), Venue.class);
assertThat(venues.size(), is(7));
}
/**
* @see DATAMONGO-360
*/
@Test
public void indexInfoIsCorrect() {
IndexOperations operations = template.indexOps(Venue.class);
List<IndexInfo> indexInfo = operations.getIndexInfo();
assertThat(indexInfo.size(), is(2));
List<IndexField> fields = indexInfo.get(0).getIndexFields();
assertThat(fields.size(), is(1));
assertThat(fields, hasItem(IndexField.create("_id", Direction.ASC)));
fields = indexInfo.get(1).getIndexFields();
assertThat(fields.size(), is(1));
assertThat(fields, hasItem(IndexField.geo("location")));
}
@Override
protected void createIndex() {
template.indexOps(Venue.class).ensureIndex(new GeospatialIndex("location").typed(GeoSpatialIndexType.GEO_2D));
}
@Override
protected void dropIndex() {
template.indexOps(Venue.class).dropIndex("location_2d");
}
}

30
spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/MongoQueryCreatorUnitTests.java

@ -1,5 +1,5 @@ @@ -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.
@ -39,6 +39,8 @@ import org.mockito.stubbing.Answer; @@ -39,6 +39,8 @@ import org.mockito.stubbing.Answer;
import org.springframework.data.geo.Distance;
import org.springframework.data.geo.Metrics;
import org.springframework.data.geo.Point;
import org.springframework.data.geo.Polygon;
import org.springframework.data.geo.Shape;
import org.springframework.data.mapping.context.MappingContext;
import org.springframework.data.mongodb.core.Person;
import org.springframework.data.mongodb.core.Venue;
@ -483,6 +485,24 @@ public class MongoQueryCreatorUnitTests { @@ -483,6 +485,24 @@ public class MongoQueryCreatorUnitTests {
assertThat(query, is(query(where("location").near(point).maxDistance(1.0))));
}
/**
* @see DATAMONGO-1136
*/
@Test
public void shouldCreateWithinQueryCorrectly() {
Point first = new Point(1, 1);
Point second = new Point(2, 2);
Point third = new Point(3, 3);
Shape shape = new Polygon(first, second, third);
PartTree tree = new PartTree("findByAddress_GeoWithin", User.class);
MongoQueryCreator creator = new MongoQueryCreator(tree, getAccessor(converter, shape), context);
Query query = creator.createQuery();
assertThat(query, is(query(where("address.geo").within(shape))));
}
interface PersonRepository extends Repository<Person, Long> {
List<Person> findByLocationNearAndFirstname(Point location, Distance maxDistance, String firstname);
@ -495,5 +515,13 @@ public class MongoQueryCreatorUnitTests { @@ -495,5 +515,13 @@ public class MongoQueryCreatorUnitTests {
@DBRef User creator;
List<String> emailAddresses;
Address address;
}
static class Address {
String street;
Point geo;
}
}

2
src/main/asciidoc/preface.adoc

@ -32,7 +32,7 @@ The jumping off ground for learning about MongoDB is http://www.mongodb.org/[www @@ -32,7 +32,7 @@ The jumping off ground for learning about MongoDB is http://www.mongodb.org/[www
Spring Data MongoDB 1.x binaries requires JDK level 6.0 and above, and http://spring.io/docs[Spring Framework] 3.2.x and above.
In terms of document stores, http://www.mongodb.org/[MongoDB] preferably version 2.4.
In terms of document stores, http://www.mongodb.org/[MongoDB] at least 2.4, preferably version 2.6.
== Additional Help Resources

4
src/main/asciidoc/reference/mongo-repositories.adoc

@ -212,11 +212,11 @@ NOTE: Note that for version 1.0 we currently don't support referring to paramete @@ -212,11 +212,11 @@ NOTE: Note that for version 1.0 we currently don't support referring to paramete
| `Within`
| `findByLocationWithin(Circle circle)`
| `{"location" : {"$within" : {"$center" : [ [x, y], distance]}}}`
| `{"location" : {"$geoWithin" : {"$center" : [ [x, y], distance]}}}`
| `Within`
| `findByLocationWithin(Box box)`
| `{"location" : {"$within" : {"$box" : [ [x1, y1], x2, y2]}}}True`
| `{"location" : {"$geoWithin" : {"$box" : [ [x1, y1], x2, y2]}}}`
| `IsTrue, True`
| `findByActiveIsTrue()`

14
src/main/asciidoc/reference/mongodb.adoc

@ -1041,9 +1041,9 @@ As you can see most methods return the `Criteria` object to provide a fluent sty @@ -1041,9 +1041,9 @@ As you can see most methods return the `Criteria` object to provide a fluent sty
There are also methods on the Criteria class for geospatial queries. Here is a listing but look at the section on <<mongo.geospatial,GeoSpatial Queries>> to see them in action.
* `Criteria` *withinCenter* `(Circle circle)` Creates a geospatial criterion using `$within $center` operators
* `Criteria` *withinCenterSphere* `(Circle circle)` Creates a geospatial criterion using `$within $center` operators. This is only available for MongoDB 1.7 and higher.
* `Criteria` *withinBox* `(Box box)` Creates a geospatial criterion using a `$within $box` operation ``
* `Criteria` *within* `(Circle circle)` Creates a geospatial criterion using `$geoWithin $center` operators.
* `Criteria` *within* `(Box box)` Creates a geospatial criterion using a `$geoWithin $box` operation.
* `Criteria` *withinSphere* `(Circle circle)` Creates a geospatial criterion using `$geoWithin $center` operators.
* `Criteria` *near* `(Point point)` Creates a geospatial criterion using a `$near `operation
* `Criteria` *nearSphere* `(Point point)` Creates a geospatial criterion using `$nearSphere$center` operations. This is only available for MongoDB 1.7 and higher.
* `Criteria` *maxDistance* `(double maxDistance)` Creates a geospatial criterion using the `$maxDistance` operation, for use with $near.
@ -1073,7 +1073,7 @@ The query methods need to specify the target type T that will be returned and th @@ -1073,7 +1073,7 @@ The query methods need to specify the target type T that will be returned and th
[[mongo.geospatial]]
=== GeoSpatial Queries
MongoDB supports GeoSpatial queries through the use of operators such as `$near`, `$within`, and `$nearSphere`. Methods specific to geospatial queries are available on the `Criteria` class. There are also a few shape classes, `Box`, `Circle`, and `Point` that are used in conjunction with geospatial related `Criteria` methods.
MongoDB supports GeoSpatial queries through the use of operators such as `$near`, `$within`, `geoWithin` and `$nearSphere`. Methods specific to geospatial queries are available on the `Criteria` class. There are also a few shape classes, `Box`, `Circle`, and `Point` that are used in conjunction with geospatial related `Criteria` methods.
To understand how to perform GeoSpatial queries we will use the following Venue class taken from the integration tests.which relies on using the rich `MappingMongoConverter`.
@ -1122,7 +1122,7 @@ To find locations within a `Circle`, the following query can be used. @@ -1122,7 +1122,7 @@ To find locations within a `Circle`, the following query can be used.
----
Circle circle = new Circle(-73.99171, 40.738868, 0.01);
List<Venue> venues =
template.find(new Query(Criteria.where("location").withinCenter(circle)), Venue.class);
template.find(new Query(Criteria.where("location").within(circle)), Venue.class);
----
To find venues within a `Circle` using spherical coordinates the following query can be used
@ -1131,7 +1131,7 @@ To find venues within a `Circle` using spherical coordinates the following query @@ -1131,7 +1131,7 @@ To find venues within a `Circle` using spherical coordinates the following query
----
Circle circle = new Circle(-73.99171, 40.738868, 0.003712240453784);
List<Venue> venues =
template.find(new Query(Criteria.where("location").withinCenterSphere(circle)), Venue.class);
template.find(new Query(Criteria.where("location").withinSphere(circle)), Venue.class);
----
To find venues within a `Box` the following query can be used
@ -1141,7 +1141,7 @@ To find venues within a `Box` the following query can be used @@ -1141,7 +1141,7 @@ To find venues within a `Box` the following query can be used
//lower-left then upper-right
Box box = new Box(new Point(-73.99756, 40.73083), new Point(-73.988135, 40.741404));
List<Venue> venues =
template.find(new Query(Criteria.where("location").withinBox(box)), Venue.class);
template.find(new Query(Criteria.where("location").within(box)), Venue.class);
----
To find venues near a `Point`, the following query can be used

Loading…
Cancel
Save