From ec6cec99b76bace9ecb268bd6c83586ce66138ff Mon Sep 17 00:00:00 2001 From: Jon Brisbin Date: Thu, 7 Apr 2011 10:47:47 -0500 Subject: [PATCH] DATADOC-87 - Created GeoSpatialIndexed annotation and modified index creation listener to create geospatial indexes. Also added test case for same. --- .../mongodb/index/GeoSpatialIndexed.java | 68 ++++++++++++++++ .../MongoPersistentEntityIndexCreator.java | 42 ++++++++++ .../mongodb/mapping/GeoIndexedTests.java | 81 +++++++++++++++++++ .../document/mongodb/mapping/GeoLocation.java | 50 ++++++++++++ 4 files changed, 241 insertions(+) create mode 100644 spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/index/GeoSpatialIndexed.java create mode 100644 spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/mapping/GeoIndexedTests.java create mode 100644 spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/mapping/GeoLocation.java diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/index/GeoSpatialIndexed.java b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/index/GeoSpatialIndexed.java new file mode 100644 index 000000000..ca24dbd8d --- /dev/null +++ b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/index/GeoSpatialIndexed.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2011 by the original author(s). + * + * 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.index; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Mark a class property to be indexed using MongoDB's geospatial indexing feature. + * + * @author Jon Brisbin + */ +@Target(ElementType.FIELD) +@Retention(RetentionPolicy.RUNTIME) +public @interface GeoSpatialIndexed { + + /** + * Name of the property in the document that contains the [x, y] or radial coordinates to index. + * + * @return + */ + String name() default ""; + + /** + * Name of the collection in which to create the index. + * + * @return + */ + String collection() default ""; + + /** + * Minimum value for indexed values. + * + * @return + */ + int min() default 0; + + /** + * Maximum value for indexed values. + * + * @return + */ + int max() default 0; + + /** + * Bits of precision for boundary calculations. + * + * @return + */ + int bits() default 26; + +} diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/mapping/MongoPersistentEntityIndexCreator.java b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/mapping/MongoPersistentEntityIndexCreator.java index 2f624fafa..fae0358db 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/mapping/MongoPersistentEntityIndexCreator.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/mapping/MongoPersistentEntityIndexCreator.java @@ -34,6 +34,7 @@ import org.springframework.data.document.mongodb.CollectionCallback; import org.springframework.data.document.mongodb.MongoTemplate; import org.springframework.data.document.mongodb.index.CompoundIndex; import org.springframework.data.document.mongodb.index.CompoundIndexes; +import org.springframework.data.document.mongodb.index.GeoSpatialIndexed; import org.springframework.data.document.mongodb.index.IndexDirection; import org.springframework.data.document.mongodb.index.Indexed; import org.springframework.data.mapping.PropertyHandler; @@ -130,6 +131,20 @@ public class MongoPersistentEntityIndexCreator implements ApplicationListener() { + public Object doInCollection(DBCollection collection) throws MongoException, DataAccessException { + DBObject defObj = new BasicDBObject(); + defObj.put(name, "2d"); + + DBObject opts = new BasicDBObject(); + // Min + if (min != 0) { + opts.put("min", min); + } + // Max + if (max != 0) { + opts.put("max", max); + } + // Bits + opts.put("bits", bits); + collection.ensureIndex(defObj, opts); + return null; + } + }); + } + } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/mapping/GeoIndexedTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/mapping/GeoIndexedTests.java new file mode 100644 index 000000000..cbc0506af --- /dev/null +++ b/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/mapping/GeoIndexedTests.java @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2011 by the original author(s). + * + * 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.mapping; + +import static org.junit.Assert.*; + +import java.util.List; + +import com.mongodb.DB; +import com.mongodb.DBCollection; +import com.mongodb.DBObject; +import com.mongodb.Mongo; +import com.mongodb.MongoException; +import org.junit.Before; +import org.junit.Test; +import org.springframework.context.ApplicationContext; +import org.springframework.context.support.ClassPathXmlApplicationContext; +import org.springframework.dao.DataAccessException; +import org.springframework.data.document.mongodb.CollectionCallback; +import org.springframework.data.document.mongodb.MongoTemplate; + +/** + * @author Jon Brisbin + */ +public class GeoIndexedTests { + + private final String[] collectionsToDrop = new String[]{ + "geolocation" + }; + + ApplicationContext applicationContext; + MongoTemplate template; + MongoMappingContext mappingContext; + + @Before + public void setUp() throws Exception { + Mongo mongo = new Mongo(); + DB db = mongo.getDB("database"); + for (String coll : collectionsToDrop) { + db.getCollection(coll).drop(); + } + applicationContext = new ClassPathXmlApplicationContext("/mapping.xml"); + template = applicationContext.getBean(MongoTemplate.class); + mappingContext = applicationContext.getBean(MongoMappingContext.class); + } + + @Test + public void testGeoLocation() { + GeoLocation geo = new GeoLocation(new double[]{40.714346, -74.005966}); + template.insert(geo); + + boolean hasIndex = template.execute("geolocation", new CollectionCallback() { + public Boolean doInCollection(DBCollection collection) throws MongoException, DataAccessException { + List indexes = collection.getIndexInfo(); + for (DBObject dbo : indexes) { + if ("location_2d".equals(dbo.get("name"))) { + return true; + } + } + return false; + } + }); + + assertTrue(hasIndex); + } + +} diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/mapping/GeoLocation.java b/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/mapping/GeoLocation.java new file mode 100644 index 000000000..91e935914 --- /dev/null +++ b/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/mapping/GeoLocation.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2011 by the original author(s). + * + * 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.mapping; + +import org.bson.types.ObjectId; +import org.springframework.data.annotation.Id; +import org.springframework.data.document.mongodb.index.GeoSpatialIndexed; + +/** + * @author Jon Brisbin + */ +@Document +public class GeoLocation { + + @Id + private ObjectId id; + @GeoSpatialIndexed + private double[] location; + + public GeoLocation(double[] location) { + this.location = location; + } + + public ObjectId getId() { + return id; + } + + public double[] getLocation() { + return location; + } + + public void setLocation(double[] location) { + this.location = location; + } + +}