Browse Source

DATADOC-67 - Criteria API to support keywords for geo search

pull/1/head
Mark Pollack 15 years ago
parent
commit
2e874e6dbc
  1. 97
      spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/geo/Box.java
  2. 38
      spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/geo/Point.java
  3. 43
      spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/query/Criteria.java
  4. 41
      spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/GeoSpatialTests.java
  5. 3
      spring-data-mongodb/src/test/resources/geospatial.xml

97
spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/geo/Box.java

@ -0,0 +1,97 @@ @@ -0,0 +1,97 @@
/*
* 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.document.mongodb.geo;
/**
* Represents a geospatial box value
* @author Mark Pollack
*
*/
public class Box {
private double xmin;
private double ymin;
private double xmax;
private double ymax;
public Box(Point lowerLeft, Point upperRight) {
xmin = lowerLeft.getX();
ymin = lowerLeft.getY();
xmax = upperRight.getX();
ymax = upperRight.getY();
}
public Box(double[] lowerLeft, double[] upperRight) {
xmin = lowerLeft[0];
ymin = lowerLeft[1];
xmax = upperRight[0];
ymax = upperRight[1];
}
public Point getLowerLeft() {
return new Point(xmin, ymin);
}
public Point getUpperRight() {
return new Point(xmax, ymax);
}
@Override
public String toString() {
return "Box [xmin=" + xmin + ", ymin=" + ymin + ", xmax=" + xmax
+ ", ymax=" + ymax + "]";
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
long temp;
temp = Double.doubleToLongBits(xmax);
result = prime * result + (int) (temp ^ (temp >>> 32));
temp = Double.doubleToLongBits(xmin);
result = prime * result + (int) (temp ^ (temp >>> 32));
temp = Double.doubleToLongBits(ymax);
result = prime * result + (int) (temp ^ (temp >>> 32));
temp = Double.doubleToLongBits(ymin);
result = prime * result + (int) (temp ^ (temp >>> 32));
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Box other = (Box) obj;
if (Double.doubleToLongBits(xmax) != Double.doubleToLongBits(other.xmax))
return false;
if (Double.doubleToLongBits(xmin) != Double.doubleToLongBits(other.xmin))
return false;
if (Double.doubleToLongBits(ymax) != Double.doubleToLongBits(other.ymax))
return false;
if (Double.doubleToLongBits(ymin) != Double.doubleToLongBits(other.ymin))
return false;
return true;
}
}

38
spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/geo/Point.java

@ -22,38 +22,36 @@ package org.springframework.data.document.mongodb.geo; @@ -22,38 +22,36 @@ package org.springframework.data.document.mongodb.geo;
*/
public class Point {
private double latitude;
private double x;
private double longitude;
private double y;
public Point(double latitude, double longitude) {
this.latitude = latitude;
this.longitude = longitude;
public Point(double x, double y) {
this.x = x;
this.y = y;
}
public Point(Point point) {
this.latitude = point.latitude;
this.longitude = point.longitude;
this.x = point.x;
this.y = point.y;
}
public double getLatitude() {
return latitude;
public double getX() {
return x;
}
public double getLongitude() {
return longitude;
public double getY() {
return y;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
long temp;
temp = Double.doubleToLongBits(latitude);
temp = Double.doubleToLongBits(x);
result = prime * result + (int) (temp ^ (temp >>> 32));
temp = Double.doubleToLongBits(longitude);
temp = Double.doubleToLongBits(y);
result = prime * result + (int) (temp ^ (temp >>> 32));
return result;
}
@ -67,18 +65,18 @@ public class Point { @@ -67,18 +65,18 @@ public class Point {
if (getClass() != obj.getClass())
return false;
Point other = (Point) obj;
if (Double.doubleToLongBits(latitude) != Double
.doubleToLongBits(other.latitude))
if (Double.doubleToLongBits(x) != Double
.doubleToLongBits(other.x))
return false;
if (Double.doubleToLongBits(longitude) != Double
.doubleToLongBits(other.longitude))
if (Double.doubleToLongBits(y) != Double
.doubleToLongBits(other.y))
return false;
return true;
}
@Override
public String toString() {
return "Point [latitude=" + latitude + ", longitude=" + longitude + "]";
return "Point [latitude=" + x + ", longitude=" + y + "]";
}

43
spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/query/Criteria.java

@ -23,6 +23,7 @@ import java.util.List; @@ -23,6 +23,7 @@ import java.util.List;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
import org.springframework.data.document.InvalidDocumentStoreApiUsageException;
import org.springframework.data.document.mongodb.geo.Box;
import org.springframework.data.document.mongodb.geo.Circle;
import org.springframework.data.document.mongodb.geo.Point;
@ -231,11 +232,11 @@ public class Criteria implements CriteriaDefinition { @@ -231,11 +232,11 @@ public class Criteria implements CriteriaDefinition {
/**
* Creates a geospatial criterion using a $within operation
* Creates a geospatial criterion using a $within $center operation
* @param circle
* @return
*/
public Criteria within(Circle circle) {
public Criteria withinCenter(Circle circle) {
LinkedList list = new LinkedList();
list.addLast(circle.getCenter());
list.add(circle.getRadius());
@ -243,13 +244,49 @@ public class Criteria implements CriteriaDefinition { @@ -243,13 +244,49 @@ public class Criteria implements CriteriaDefinition {
return this;
}
/**
* Creates a geospatial criterion using a $within $center operation. This is only available for Mongo 1.7 and higher.
* @param circle
* @return
*/
public Criteria withinCenterSphere(Circle circle) {
LinkedList list = new LinkedList();
list.addLast(circle.getCenter());
list.add(circle.getRadius());
criteria.put("$within", new BasicDBObject("$centerSphere", list));
return this;
}
/**
* Creates a geospatial criterion using a $within $box operation
* @param circle
* @return
*/
public Criteria withinBox(Box box) {
LinkedList<double[]> list = new LinkedList<double[]>();
list.addLast(new double[]{ box.getLowerLeft().getX(), box.getLowerLeft().getY()} );
list.addLast(new double[]{ box.getUpperRight().getX(), box.getUpperRight().getY()} );
criteria.put("$within", new BasicDBObject("$box", list));
return this;
}
/**
* Creates a geospatial criterion using a $near operation
* @param point
* @return
*/
public Criteria near(Point point) {
criteria.put("$near", new double[]{point.getLatitude(), point.getLongitude()});
criteria.put("$near", new double[]{point.getX(), point.getY()});
return this;
}
/**
* Creates a geospatial criterion using a $nearSphere operation. This is only available for Mongo 1.7 and higher.
* @param point
* @return
*/
public Criteria nearSphere(Point point) {
criteria.put("$nearSphere", new double[]{point.getX(), point.getY()});
return this;
}

41
spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/GeoSpatialTests.java

@ -31,8 +31,10 @@ import org.springframework.beans.factory.annotation.Autowired; @@ -31,8 +31,10 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.dao.DataAccessException;
import org.springframework.data.document.mongodb.geo.Box;
import org.springframework.data.document.mongodb.geo.Circle;
import org.springframework.data.document.mongodb.geo.Point;
import org.springframework.data.document.mongodb.monitor.ServerInfo;
import org.springframework.data.document.mongodb.query.Criteria;
import org.springframework.data.document.mongodb.query.GeospatialIndex;
import org.springframework.data.document.mongodb.query.Query;
@ -57,10 +59,12 @@ public class GeoSpatialTests { @@ -57,10 +59,12 @@ public class GeoSpatialTests {
ApplicationContext applicationContext;
MongoTemplate template;
ServerInfo serverInfo;
@Before
public void setUp() throws Exception {
Mongo mongo = new Mongo();
serverInfo = new ServerInfo(mongo);
DB db = mongo.getDB("geospatial");
for (String coll : collectionsToDrop) {
db.getCollection(coll).drop();
@ -90,20 +94,53 @@ public class GeoSpatialTests { @@ -90,20 +94,53 @@ public class GeoSpatialTests {
template.insert(new Venue("Maplewood, NJ", -74.2713, 40.73137));
}
/*
public void geoNear() {
GeoNearResult<Venue> geoNearResult = template.geoNear(new Query(Criteria.where("type").is("Office")), Venue.class,
GeoNearCriteria.near(2,3).num(10).maxDistance(10).distanceMultiplier(10).spherical(true));
}*/
@Test
public void withinCircle() {
public void withinCenter() {
Circle circle = new Circle(-73.99171, 40.738868, 0.01);
List<Venue> venues = template.find(new Query(Criteria.where("location").within(circle)), Venue.class);
List<Venue> venues = template.find(new Query(Criteria.where("location").withinCenter(circle)), Venue.class);
assertThat(venues.size(), equalTo(7));
}
@Test
@Ignore("run only on v 1.7.0 server or greater")
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));
}
@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));
}
@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));
}
@Test
@Ignore("run only on v 1.7.0 server or greater")
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));
}
@Test
public void searchAllData() {

3
spring-data-mongodb/src/test/resources/geospatial.xml

@ -6,8 +6,9 @@ @@ -6,8 +6,9 @@
http://www.springframework.org/schema/data/mongo http://www.springframework.org/schema/data/mongo/spring-mongo-1.0.xsd">
<mongo:mongo host="localhost" port="27017"/>
<mongo:mapping-converter base-package="org.springframework.data.document.mongodb.mapping"/>
<bean id="mongoTemplate" class="org.springframework.data.document.mongodb.MongoTemplate">
<constructor-arg ref="mongo"/>
<constructor-arg value="geospatial"/>

Loading…
Cancel
Save