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

This commit is contained in:
Mark Pollack
2011-04-05 16:37:28 -04:00
parent b43b5aa4b2
commit 4175791d0b
4 changed files with 142 additions and 12 deletions

View File

@@ -398,7 +398,7 @@ public class MongoTemplate implements InitializingBean, MongoOperations, Applica
}
return result;
} catch (MongoException e) {
} catch (RuntimeException e) {
throw potentiallyConvertRuntimeException(e);
}
}

View File

@@ -0,0 +1,87 @@
/*
* 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 point value
* @author Mark Pollack
*
*/
public class Point {
private double latitude;
private double longitude;
public Point(double latitude, double longitude) {
this.latitude = latitude;
this.longitude = longitude;
}
public Point(Point point) {
this.latitude = point.latitude;
this.longitude = point.longitude;
}
public double getLatitude() {
return latitude;
}
public double getLongitude() {
return longitude;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
long temp;
temp = Double.doubleToLongBits(latitude);
result = prime * result + (int) (temp ^ (temp >>> 32));
temp = Double.doubleToLongBits(longitude);
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;
Point other = (Point) obj;
if (Double.doubleToLongBits(latitude) != Double
.doubleToLongBits(other.latitude))
return false;
if (Double.doubleToLongBits(longitude) != Double
.doubleToLongBits(other.longitude))
return false;
return true;
}
@Override
public String toString() {
return "Point [latitude=" + latitude + ", longitude=" + longitude + "]";
}
}

View File

@@ -24,6 +24,7 @@ import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
import org.springframework.data.document.InvalidDocumentStoreApiUsageException;
import org.springframework.data.document.mongodb.geo.Circle;
import org.springframework.data.document.mongodb.geo.Point;
public class Criteria implements CriteriaDefinition {
@@ -230,18 +231,37 @@ public class Criteria implements CriteriaDefinition {
/**
* Creates a geospatial criterion using a $
* Creates a geospatial criterion using a $within operation
* @param circle
* @return
*/
public Criteria within(Circle circle) {
LinkedList list = new LinkedList();
list.addLast(circle.getCenter());
list.add(circle.getRadius());
//BasicDBObject dbo = new BasicDBObject("$within", new BasicDBObject("$center", list));
list.add(circle.getRadius());
criteria.put("$within", new BasicDBObject("$center", 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()});
return this;
}
/**
* Creates a geospatical criterion using a $maxDistance operation, for use with $near
* @param maxDistance
* @return
*/
public Criteria maxDistance(double maxDistance) {
criteria.put("$maxDistance", maxDistance);
return this;
}
/**
* Creates a criterion using the $elemMatch operator

View File

@@ -26,35 +26,51 @@ import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
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.Circle;
import org.springframework.data.document.mongodb.geo.Point;
import org.springframework.data.document.mongodb.query.Criteria;
import org.springframework.data.document.mongodb.query.GeospatialIndex;
import org.springframework.data.document.mongodb.query.Query;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.mongodb.DB;
import com.mongodb.DBCollection;
import com.mongodb.DBObject;
import com.mongodb.Mongo;
import com.mongodb.MongoException;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:geospatial.xml")
@Ignore
/**
* Modified from https://github.com/deftlabs/mongo-java-geospatial-example
* @author Mark Pollack
*
*/
//@RunWith(SpringJUnit4ClassRunner.class)
//@ContextConfiguration("classpath:geospatial.xml")
public class GeoSpatialTests {
@Autowired
private final String[] collectionsToDrop = new String[]{"newyork"};
ApplicationContext applicationContext;
MongoTemplate template;
@Before
public void setUp() {
template.dropCollection(template.getDefaultCollectionName());
public void setUp() throws Exception {
Mongo mongo = new Mongo();
DB db = mongo.getDB("geospatial");
for (String coll : collectionsToDrop) {
db.getCollection(coll).drop();
}
applicationContext = new ClassPathXmlApplicationContext("/geospatial.xml");
template = applicationContext.getBean(MongoTemplate.class);
//template.dropCollection(template.getDefaultCollectionName());
template.ensureIndex(new GeospatialIndex("location"));
addVenues();
}
private void addVenues() {
// Data taken from https://github.com/deftlabs/mongo-java-geospatial-example
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));
@@ -77,6 +93,13 @@ public class GeoSpatialTests {
List<Venue> venues = template.find(new Query(Criteria.where("location").within(circle)), Venue.class);
assertThat(venues.size(), equalTo(8));
}
@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(8));
}
@Test
public void indexCreated() {