DATADOC-67 - Criteria API to support keywords for geo search
This commit is contained in:
@@ -49,7 +49,7 @@ public class MongoAdmin implements MongoAdminOperations {
|
||||
*/
|
||||
@ManagedOperation
|
||||
public void dropDatabase(String databaseName) {
|
||||
mongo.getDB(databaseName).dropDatabase();
|
||||
getDB(databaseName).dropDatabase();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
@@ -57,7 +57,7 @@ public class MongoAdmin implements MongoAdminOperations {
|
||||
*/
|
||||
@ManagedOperation
|
||||
public void createDatabase(String databaseName) {
|
||||
mongo.getDB(databaseName);
|
||||
getDB(databaseName);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
@@ -65,7 +65,7 @@ public class MongoAdmin implements MongoAdminOperations {
|
||||
*/
|
||||
@ManagedOperation
|
||||
public String getDatabaseStats(String databaseName) {
|
||||
return mongo.getDB("testAdminDb").getStats().toString();
|
||||
return getDB(databaseName).getStats().toString();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -88,7 +88,7 @@ public class MongoAdmin implements MongoAdminOperations {
|
||||
}
|
||||
|
||||
|
||||
public DB getDb(String databaseName) {
|
||||
DB getDB(String databaseName) {
|
||||
return MongoDbUtils.getDB(mongo, databaseName, username, password == null ? null : password.toCharArray());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,9 +92,9 @@ public abstract class MongoDbUtils {
|
||||
|
||||
LOGGER.debug("Opening Mongo DB");
|
||||
DB db = mongo.getDB(databaseName);
|
||||
boolean creadentialsGiven = username != null && password != null;
|
||||
boolean credentialsGiven = username != null && password != null;
|
||||
|
||||
if (creadentialsGiven && !db.authenticate(username, password)) {
|
||||
if (credentialsGiven && !db.authenticate(username, password)) {
|
||||
throw new CannotGetMongoDbConnectionException("Failed to authenticate with Mongo using the given credentials");
|
||||
}
|
||||
|
||||
|
||||
@@ -18,9 +18,12 @@ package org.springframework.data.document.mongodb;
|
||||
import com.mongodb.MongoException;
|
||||
import com.mongodb.MongoException.DuplicateKey;
|
||||
import com.mongodb.MongoException.Network;
|
||||
import com.mongodb.MongoInternalException;
|
||||
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.dao.DataAccessResourceFailureException;
|
||||
import org.springframework.dao.DataIntegrityViolationException;
|
||||
import org.springframework.dao.InvalidDataAccessResourceUsageException;
|
||||
import org.springframework.dao.support.PersistenceExceptionTranslator;
|
||||
import org.springframework.data.document.UncategorizedDocumentStoreException;
|
||||
|
||||
@@ -55,6 +58,9 @@ public class MongoExceptionTranslator implements PersistenceExceptionTranslator
|
||||
if (ex instanceof MongoException) {
|
||||
return new UncategorizedDocumentStoreException(ex.getMessage(), ex);
|
||||
}
|
||||
if (ex instanceof MongoInternalException) {
|
||||
return new InvalidDataAccessResourceUsageException(ex.getMessage(), ex);
|
||||
}
|
||||
|
||||
// If we get here, we have an exception that resulted from user code,
|
||||
// rather than the persistence provider, so we return null to indicate
|
||||
|
||||
@@ -239,7 +239,7 @@ public class MappingMongoConverter implements MongoConverter, ApplicationContext
|
||||
|
||||
// Set the ID
|
||||
PersistentProperty idProperty = entity.getIdProperty();
|
||||
if (dbo.containsField("_id") || null != idProperty) {
|
||||
if (dbo.containsField("_id") && null != idProperty) {
|
||||
Object idObj = dbo.get("_id");
|
||||
try {
|
||||
MappingBeanHelper.setProperty(instance, idProperty, idObj, useFieldAccessOnly);
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* Represents a geospatial circle value
|
||||
* @author Mark Pollack
|
||||
*
|
||||
*/
|
||||
public class Circle {
|
||||
|
||||
private double[] center;
|
||||
private double radius;
|
||||
|
||||
public Circle(double centerX, double centerY, double radius) {
|
||||
this.center = new double[] { centerX, centerY };
|
||||
this.radius = radius;
|
||||
}
|
||||
|
||||
public double[] getCenter() {
|
||||
return center;
|
||||
}
|
||||
|
||||
public double getRadius() {
|
||||
return radius;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Circle [center=" + Arrays.toString(center) + ", radius=" + radius
|
||||
+ "]";
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -17,11 +17,13 @@ package org.springframework.data.document.mongodb.query;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedList;
|
||||
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.Circle;
|
||||
|
||||
public class Criteria implements CriteriaDefinition {
|
||||
|
||||
@@ -225,6 +227,21 @@ public class Criteria implements CriteriaDefinition {
|
||||
criteria.put("$regex", re);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a geospatial criterion using a $
|
||||
* @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));
|
||||
criteria.put("$within", new BasicDBObject("$center", list));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a criterion using the $elemMatch operator
|
||||
@@ -244,6 +261,8 @@ public class Criteria implements CriteriaDefinition {
|
||||
public void or(List<Query> queries) {
|
||||
criteria.put("$or", queries);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public String getKey() {
|
||||
return this.key;
|
||||
|
||||
@@ -1,30 +1,109 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.data.document.mongodb.geo.Circle;
|
||||
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.BasicDBObject;
|
||||
import com.mongodb.DBCollection;
|
||||
import com.mongodb.DBObject;
|
||||
import com.mongodb.MongoException;
|
||||
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration("classpath:geospatial.xml")
|
||||
public class GeoSpatialTests {
|
||||
|
||||
|
||||
@Autowired
|
||||
MongoTemplate template;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
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));
|
||||
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 withinCircle() {
|
||||
|
||||
Circle circle = new Circle(-73.99171, 40.738868, 0.01);
|
||||
List<Venue> venues = template.find(new Query(Criteria.where("location").within(circle)), Venue.class);
|
||||
assertThat(venues.size(), equalTo(8));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void indexCreated() {
|
||||
assertThat(template, notNullValue());
|
||||
Venue foundVenue = template.findOne(
|
||||
new Query(Criteria.where("name").is("Penn Station")), Venue.class);
|
||||
assertThat(foundVenue, notNullValue());
|
||||
List<Venue> venues = template.getCollection(Venue.class);
|
||||
assertThat(venues.size(), equalTo(13));
|
||||
|
||||
List<DBObject> indexInfo = getIndexInfo();
|
||||
assertThat(indexInfo.size(), equalTo(2));
|
||||
assertThat(indexInfo.get(1).get("name").toString(), equalTo("location_2d"));
|
||||
assertThat(indexInfo.get(1).get("ns").toString(),
|
||||
equalTo("geospatial.newyork"));
|
||||
}
|
||||
|
||||
// TODO move to MongoAdmin
|
||||
public List<DBObject> getIndexInfo() {
|
||||
return template.execute(new CollectionCallback<List<DBObject>>() {
|
||||
|
||||
public List<DBObject> doInCollection(DBCollection collection)
|
||||
throws MongoException, DataAccessException {
|
||||
return collection.getIndexInfo();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void geoIndex() {
|
||||
assertThat(template, notNullValue());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.springframework.data.annotation.PersistenceConstructor;
|
||||
import org.springframework.data.document.mongodb.mapping.Document;
|
||||
|
||||
@Document
|
||||
public class Venue {
|
||||
|
||||
private String id;
|
||||
private String name;
|
||||
private Double[] location;
|
||||
|
||||
@PersistenceConstructor
|
||||
Venue(String name, Double[] location) {
|
||||
super();
|
||||
this.name = name;
|
||||
this.location = location;
|
||||
}
|
||||
|
||||
public Venue(String name, double x, double y) {
|
||||
super();
|
||||
this.name = name;
|
||||
this.location = new Double[] { x, y };
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public Double[] getLocation() {
|
||||
return location;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Venue [id=" + id + ", name=" + name + ", location="
|
||||
+ Arrays.toString(location) + "]";
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user