DATADOC-67 - Criteria API to support keywords for geo search
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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 {
|
||||
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 + "]";
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
|
||||
/**
|
||||
* 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 {
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
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 {
|
||||
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() {
|
||||
|
||||
@@ -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"/>
|
||||
|
||||
Reference in New Issue
Block a user