DATADOC-293 - Added Polygon abstraction to Criteria.

Introduced Polygon value object to capture a list of Points. Polished implementation of Circle (equals(…) and hashCode()) and API of Criteria. Added some additional unit tests. Introduced Shape interface to allow streamling the implementation of building within-Criterias.

Ignoring the tests for polygons right now until we have updated the Mongo instance on the CI server to 2.0.
This commit is contained in:
Oliver Gierke
2011-10-11 12:29:54 +02:00
parent e405bf574c
commit 80641a0943
11 changed files with 467 additions and 91 deletions

View File

@@ -15,6 +15,9 @@
*/
package org.springframework.data.mongodb.core.geo;
import java.util.ArrayList;
import java.util.List;
import org.springframework.data.mongodb.core.mapping.Field;
import org.springframework.util.Assert;
@@ -24,7 +27,7 @@ import org.springframework.util.Assert;
* @author Mark Pollack
* @author Oliver Gierke
*/
public class Box {
public class Box implements Shape {
@Field(order = 10)
private final Point first;
@@ -53,6 +56,25 @@ public class Box {
return second;
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.geo.Shape#asList()
*/
public List<? extends Object> asList() {
List<List<Double>> list = new ArrayList<List<Double>>();
list.add(getLowerLeft().asList());
list.add(getUpperRight().asList());
return list;
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.geo.Shape#getCommand()
*/
public String getCommand() {
return "$box";
}
@Override
public String toString() {
return String.format("Box [%s, %s]", first, second);

View File

@@ -15,6 +15,9 @@
*/
package org.springframework.data.mongodb.core.geo;
import java.util.ArrayList;
import java.util.List;
import org.springframework.data.annotation.PersistenceConstructor;
import org.springframework.util.Assert;
@@ -24,33 +27,112 @@ import org.springframework.util.Assert;
* @author Mark Pollack
* @author Oliver Gierke
*/
public class Circle {
public class Circle implements Shape {
private Point center;
private double radius;
private final Point center;
private final double radius;
/**
* Creates a new {@link Circle} from the given {@link Point} and radius.
*
* @param center must not be {@literal null}.
* @param radius must be greater or equal to zero.
*/
@PersistenceConstructor
public Circle(Point center, double radius) {
Assert.notNull(center);
Assert.isTrue(radius >= 0, "Radius must not be negative!");
this.center = center;
this.radius = radius;
}
/**
* Creates a new {@link Circle} from the given coordinates and radius.
*
* @param centerX
* @param centerY
* @param radius must be greater or equal to zero.
*/
public Circle(double centerX, double centerY, double radius) {
this(new Point(centerX, centerY), radius);
}
/**
* Returns the center of the {@link Circle}.
*
* @return will never be {@literal null}.
*/
public Point getCenter() {
return center;
}
/**
* Returns the radius of the {@link Circle}.
*
* @return
*/
public double getRadius() {
return radius;
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.geo.Shape#asList()
*/
public List<Object> asList() {
List<Object> result = new ArrayList<Object>();
result.add(getCenter().asList());
result.add(getRadius());
return result;
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.geo.Shape#getCommand()
*/
public String getCommand() {
return "$center";
}
/*
* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return String.format("Circle [center=%s, radius=%f]", center, radius);
}
/* (non-Javadoc)
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null || !getClass().equals(obj.getClass())) {
return false;
}
Circle that = (Circle) obj;
return this.center.equals(that.center) && this.radius == that.radius;
}
/*
* (non-Javadoc)
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
int result = 17;
result += 31 * center.hashCode();
result += 31 * radius;
return result;
}
}

View File

@@ -0,0 +1,113 @@
/*
* Copyright 2011 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 java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import org.springframework.util.Assert;
/**
* Simple value object to represent a {@link Polygon}.
*
* @author Oliver Gierke
*/
public class Polygon implements Shape, Iterable<Point> {
private final List<Point> points;
/**
* Creates a new {@link Polygon} for the given Points.
*
* @param x
* @param y
* @param z
* @param others
*/
public Polygon(Point x, Point y, Point z, Point... others) {
Assert.notNull(x);
Assert.notNull(y);
Assert.notNull(z);
Assert.notNull(others);
this.points = new ArrayList<Point>(3 + others.length);
this.points.addAll(Arrays.asList(x, y, z));
this.points.addAll(Arrays.asList(others));
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.geo.Shape#asList()
*/
public List<List<Double>> asList() {
List<List<Double>> result = new ArrayList<List<Double>>();
for (Point point : points) {
result.add(point.asList());
}
return result;
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.geo.Shape#getCommand()
*/
public String getCommand() {
return "$polygon";
}
/*
* (non-Javadoc)
* @see java.lang.Iterable#iterator()
*/
public Iterator<Point> iterator() {
return this.points.iterator();
}
/*
* (non-Javadoc)
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null || !getClass().equals(obj.getClass())) {
return false;
}
Polygon that = (Polygon) obj;
return this.points.equals(that.points);
}
/*
* (non-Javadoc)
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
return points.hashCode();
}
}

View File

@@ -0,0 +1,41 @@
/*
* Copyright 2011 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 java.util.List;
/**
* Common interface for all shapes. Allows building MongoDB representations of them.
*
* @author Oliver Gierke
*/
public interface Shape {
/**
* Returns the {@link Shape} as a list of usually {@link Double} or {@link List}s of {@link Double}s. Wildcard bound
* to allow implementations to return a more concrete element type.
*
* @return
*/
List<? extends Object> asList();
/**
* Returns the command to be used to create the {@literal $within} criterion.
*
* @return
*/
String getCommand();
}

View File

@@ -20,16 +20,16 @@ import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
import org.springframework.data.mongodb.InvalidMongoDbApiUsageException;
import org.springframework.data.mongodb.core.geo.Box;
import org.springframework.data.mongodb.core.geo.Circle;
import org.springframework.data.mongodb.core.geo.Point;
import org.springframework.data.mongodb.core.geo.Shape;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
public class Criteria implements CriteriaDefinition {
/**
@@ -282,48 +282,22 @@ public class Criteria implements CriteriaDefinition {
return this;
}
/**
* Creates a geospatial criterion using a $within $center operation
*
* @param circle must not be {@literal null}
* @return
*/
public Criteria withinCenter(Circle circle) {
Assert.notNull(circle);
List<Object> list = new ArrayList<Object>();
list.add(circle.getCenter().asList());
list.add(circle.getRadius());
criteria.put("$within", new BasicDBObject("$center", list));
return this;
}
/**
* Creates a geospatial criterion using a $within $center operation. This is only available for Mongo 1.7 and higher.
*
* @param circle must not be {@literal null}
* @return
*/
public Criteria withinCenterSphere(Circle circle) {
public Criteria withinSphere(Circle circle) {
Assert.notNull(circle);
List<Object> list = new ArrayList<Object>();
list.add(circle.getCenter().asList());
list.add(circle.getRadius());
criteria.put("$within", new BasicDBObject("$centerSphere", list));
criteria.put("$within", new BasicDBObject("$centerSphere", circle.asList()));
return this;
}
/**
* Creates a geospatial criterion using a $within $box operation
*
* @param box
* @return
*/
public Criteria withinBox(Box box) {
Assert.notNull(box);
List<List<Double>> list = new ArrayList<List<Double>>();
list.add(box.getLowerLeft().asList());
list.add(box.getUpperRight().asList());
criteria.put("$within", new BasicDBObject("$box", list));
public Criteria within(Shape shape) {
Assert.notNull(shape);
criteria.put("$within", new BasicDBObject(shape.getCommand(), shape.asList()));
return this;
}

View File

@@ -19,15 +19,15 @@ import static org.springframework.data.mongodb.core.query.Criteria.*;
import java.util.Collection;
import java.util.Iterator;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.data.domain.Sort;
import org.springframework.data.mapping.context.MappingContext;
import org.springframework.data.mapping.context.PersistentPropertyPath;
import org.springframework.data.mongodb.core.geo.Box;
import org.springframework.data.mongodb.core.geo.Circle;
import org.springframework.data.mongodb.core.geo.Distance;
import org.springframework.data.mongodb.core.geo.Point;
import org.springframework.data.mongodb.core.geo.Shape;
import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.CriteriaDefinition;
@@ -211,12 +211,7 @@ class MongoQueryCreator extends AbstractQueryCreator<Query, Query> {
case WITHIN:
Object parameter = parameters.next();
if (parameter instanceof Box) {
return criteria.withinBox((Box) parameter);
} else if (parameter instanceof Circle) {
return criteria.withinCenter((Circle) parameter);
}
throw new IllegalArgumentException("Parameter has to be either Box or Circle!");
return criteria.within((Shape) parameter);
case SIMPLE_PROPERTY:
return criteria.is(parameters.nextConverted());
case NEGATING_SIMPLE_PROPERTY:

View File

@@ -0,0 +1,54 @@
/*
* Copyright 2011 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.CoreMatchers.*;
import static org.junit.Assert.*;
import org.junit.Test;
/**
* Unit tests for {@link Circle}.
*
* @author Oliver Gierke
*/
public class CircleUnitTests {
@Test(expected = IllegalArgumentException.class)
public void rejectsNullOrigin() {
new Circle(null, 0);
}
@Test(expected = IllegalArgumentException.class)
public void rejectsNegativeRadius() {
new Circle(1, 1, -1);
}
@Test
public void considersTwoCirclesEqualCorrectly() {
Circle left = new Circle(1, 1, 1);
Circle right = new Circle(1, 1, 1);
assertThat(left, is(right));
assertThat(right, is(left));
right = new Circle(new Point(1,1), 1);
assertThat(left, is(right));
assertThat(right, is(left));
}
}

View File

@@ -18,6 +18,8 @@ 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.Query.*;
import static org.springframework.data.mongodb.core.query.Criteria.*;
import java.net.UnknownHostException;
import java.util.Collection;
@@ -27,6 +29,7 @@ import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
@@ -35,7 +38,6 @@ 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.index.GeospatialIndex;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.NearQuery;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.monitor.ServerInfo;
@@ -111,70 +113,86 @@ public class GeoSpatialTests {
@Test
public void geoNear() {
NearQuery geoNear = NearQuery.near(-73,40, Metrics.KILOMETERS).num(10).maxDistance(150);
NearQuery geoNear = NearQuery.near(-73, 40, Metrics.KILOMETERS).num(10).maxDistance(150);
GeoResults<Venue> geoNearResult = template.geoNear(geoNear, Venue.class);
assertThat(geoNearResult.getContent().size(), is(not(0)));
}
@Test
public void withinCenter() {
Circle circle = new Circle(-73.99171, 40.738868, 0.01);
List<Venue> venues = template.find(new Query(Criteria.where("location").withinCenter(circle)), Venue.class);
assertThat(venues.size(), equalTo(7));
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(new Query(Criteria.where("location").withinCenterSphere(circle)), Venue.class);
assertThat(venues.size(), equalTo(11));
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));
// Box box = newBox.lowerLeft(x,y).upperRight(x,y);
List<Venue> venues = template.find(new Query(Criteria.where("location").withinBox(box)), Venue.class);
assertThat(venues.size(), equalTo(4));
List<Venue> venues = template.find(query(where("location").within(box)), Venue.class);
assertThat(venues.size(), is(4));
}
@Test
@Ignore
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(new Query(Criteria.where("location").near(point).maxDistance(0.01)), Venue.class);
assertThat(venues.size(), equalTo(7));
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);
List<Venue> venues = template.find(
new Query(Criteria.where("location").nearSphere(point).maxDistance(0.003712240453784)), Venue.class);
assertThat(venues.size(), equalTo(11));
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() {
assertThat(template, notNullValue());
Venue foundVenue = template.findOne(new Query(Criteria.where("name").is("Penn Station")), Venue.class);
assertThat(foundVenue, notNullValue());
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(), equalTo(12));
assertThat(venues.size(), is(12));
Collection<?> names = (Collection<?>) parser.parseExpression("![name]").getValue(venues);
assertThat(names.size(), equalTo(12));
org.springframework.util.Assert.notEmpty(names);
assertThat(names.size(), is(12));
}
public void indexCreated() {
List<DBObject> indexInfo = getIndexInfo(Venue.class);
LOGGER.debug(indexInfo);
assertThat(indexInfo.size(), equalTo(2));
assertThat(indexInfo.get(1).get("name").toString(), equalTo("location_2d"));
assertThat(indexInfo.get(1).get("ns").toString(), equalTo("database.newyork"));
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"));
}
// TODO move to MongoAdmin

View File

@@ -0,0 +1,54 @@
/*
* Copyright 2010-2011 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.CoreMatchers.*;
import static org.junit.Assert.*;
import org.junit.Test;
/**
* Unit tests for {@link Polygon}.
*
* @author Oliver Gierke
*/
public class PolygonUnitTests {
Point first = new Point(1, 1);
Point second = new Point(2, 2);
Point third = new Point(3, 3);
@Test(expected = IllegalArgumentException.class)
public void rejectsNullPoints() {
new Polygon(null, null, null);
}
@Test
public void createsSimplePolygon() {
Polygon polygon = new Polygon(third, second, first);
assertThat(polygon, is(notNullValue()));
}
@Test
public void isEqualForSamePoints() {
Polygon left = new Polygon(third, second, first);
Polygon right = new Polygon(third, second, first);
assertThat(left, is(right));
assertThat(right, is(left));
}
}

View File

@@ -24,6 +24,7 @@ import java.util.HashSet;
import java.util.List;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
@@ -38,6 +39,7 @@ import org.springframework.data.mongodb.core.geo.Distance;
import org.springframework.data.mongodb.core.geo.GeoResults;
import org.springframework.data.mongodb.core.geo.Metrics;
import org.springframework.data.mongodb.core.geo.Point;
import org.springframework.data.mongodb.core.geo.Polygon;
import org.springframework.data.mongodb.repository.Person.Sex;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@@ -53,7 +55,7 @@ public abstract class AbstractPersonRepositoryIntegrationTests {
protected PersonRepository repository;
Person dave, oliver, carter, boyd, stefan, leroi, alicia;
QPerson person;
List<Person> all;
@Before
@@ -67,7 +69,7 @@ public abstract class AbstractPersonRepositoryIntegrationTests {
boyd = new Person("Boyd", "Tinsley", 45);
stefan = new Person("Stefan", "Lessard", 34);
leroi = new Person("Leroi", "Moore", 41);
alicia = new Person("Alicia", "Keys", 30, Sex.FEMALE);
person = new QPerson("person");
@@ -147,17 +149,19 @@ public abstract class AbstractPersonRepositoryIntegrationTests {
@Test
public void executesPagedFinderCorrectly() throws Exception {
Page<Person> page = repository.findByLastnameLike("*a*", new PageRequest(0, 2, Direction.ASC, "lastname", "firstname"));
Page<Person> page = repository.findByLastnameLike("*a*", new PageRequest(0, 2, Direction.ASC, "lastname",
"firstname"));
assertThat(page.isFirstPage(), is(true));
assertThat(page.isLastPage(), is(false));
assertThat(page.getNumberOfElements(), is(2));
assertThat(page, hasItems(carter, stefan));
}
@Test
public void executesPagedFinderWithAnnotatedQueryCorrectly() throws Exception {
Page<Person> page = repository.findByLastnameLikeWithPageable(".*a.*", new PageRequest(0, 2, Direction.ASC, "lastname", "firstname"));
Page<Person> page = repository.findByLastnameLikeWithPageable(".*a.*", new PageRequest(0, 2, Direction.ASC,
"lastname", "firstname"));
assertThat(page.isFirstPage(), is(true));
assertThat(page.isLastPage(), is(false));
assertThat(page.getNumberOfElements(), is(2));
@@ -261,6 +265,24 @@ public abstract class AbstractPersonRepositoryIntegrationTests {
assertThat(result, hasItem(dave));
}
@Test
@Ignore
public void findsPeopleByLocationWithinPolygon() {
Point point = new Point(-73.99171, 40.738868);
dave.setLocation(point);
repository.save(dave);
Point first = new Point(-78.99171, 35.738868);
Point second = new Point(-78.99171, 45.738868);
Point third = new Point(-68.99171, 45.738868);
Point fourth = new Point(-68.99171, 35.738868);
List<Person> result = repository.findByLocationWithin(new Polygon(first, second, third, fourth));
assertThat(result.size(), is(1));
assertThat(result, hasItem(dave));
}
@Test
public void findsPagedPeopleByPredicate() throws Exception {
@@ -277,7 +299,7 @@ public abstract class AbstractPersonRepositoryIntegrationTests {
*/
@Test
public void findsPeopleBySexCorrectly() {
List<Person> females = repository.findBySex(Sex.FEMALE);
assertThat(females.size(), is(1));
assertThat(females.get(0), is(alicia));
@@ -300,12 +322,12 @@ public abstract class AbstractPersonRepositoryIntegrationTests {
@Test(expected = DuplicateKeyException.class)
public void rejectsDuplicateEmailAddressOnSave() {
assertThat(dave.getEmail(), is("dave@dmband.com"));
Person daveSyer = new Person("Dave", "Syer");
assertThat(daveSyer.getEmail(), is("dave@dmband.com"));
repository.save(daveSyer);
}
@@ -319,7 +341,7 @@ public abstract class AbstractPersonRepositoryIntegrationTests {
assertThat(result.get(0), is(dave));
assertThat(result.get(1), is(oliver));
}
/**
* @see DATADOC-236
*/
@@ -333,16 +355,16 @@ public abstract class AbstractPersonRepositoryIntegrationTests {
assertThat(result.get(3), is(dave));
assertThat(result.get(4), is(leroi));
}
@Test
public void executesGeoNearQueryForResultsCorrectly() {
Point point = new Point(-73.99171, 40.738868);
dave.setLocation(point);
repository.save(dave);
GeoResults<Person> results = repository.findByLocationNear(new Point(-73.99, 40.73), new Distance(2000, Metrics.KILOMETERS));
GeoResults<Person> results = repository.findByLocationNear(new Point(-73.99, 40.73), new Distance(2000,
Metrics.KILOMETERS));
assertThat(results.getContent().isEmpty(), is(false));
}
}

View File

@@ -26,8 +26,7 @@ import org.springframework.data.mongodb.core.geo.Circle;
import org.springframework.data.mongodb.core.geo.Distance;
import org.springframework.data.mongodb.core.geo.GeoResults;
import org.springframework.data.mongodb.core.geo.Point;
import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.data.mongodb.repository.Query;
import org.springframework.data.mongodb.core.geo.Polygon;
import org.springframework.data.mongodb.repository.Person.Sex;
import org.springframework.data.querydsl.QueryDslPredicateExecutor;
@@ -139,6 +138,8 @@ public interface PersonRepository extends MongoRepository<Person, String>, Query
List<Person> findByLocationWithin(Box box);
List<Person> findByLocationWithin(Polygon polygon);
List<Person> findBySex(Sex sex);
List<Person> findByNamedQuery(String firstname);