diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/CompoundIndex.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/CompoundIndex.java index 8c8209022..fc480bf3e 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/CompoundIndex.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/CompoundIndex.java @@ -78,6 +78,15 @@ public @interface CompoundIndex { */ String name() default ""; + /** + * If set to {@literal true} then MongoDB will ignore the given index name and instead generate a new name. Defaults + * to {@literal false}. + * + * @return + * @since 1.5 + */ + boolean useGeneratedName() default false; + /** * The collection the index will be created in. Will default to the collection the annotated domain class will be * stored in. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/GeoSpatialIndexed.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/GeoSpatialIndexed.java index d55fb783f..3bf128c14 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/GeoSpatialIndexed.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/GeoSpatialIndexed.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2013 the original author or authors. + * Copyright 2010-2014 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. @@ -25,6 +25,7 @@ import java.lang.annotation.Target; * * @author Jon Brisbin * @author Laurent Canet + * @author Thomas Darimont */ @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) @@ -37,6 +38,15 @@ public @interface GeoSpatialIndexed { */ String name() default ""; + /** + * If set to {@literal true} then MongoDB will ignore the given index name and instead generate a new name. Defaults + * to {@literal false}. + * + * @return + * @since 1.5 + */ + boolean useGeneratedName() default false; + /** * Name of the collection in which to create the index. * diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/GeospatialIndex.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/GeospatialIndex.java index 40b548334..64d8841a6 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/GeospatialIndex.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/GeospatialIndex.java @@ -58,8 +58,6 @@ public class GeospatialIndex implements IndexDefinition { */ public GeospatialIndex named(String name) { - Assert.hasText(name, "Name must have text!"); - this.name = name; return this; } @@ -152,12 +150,12 @@ public class GeospatialIndex implements IndexDefinition { public DBObject getIndexOptions() { - if (name == null && min == null && max == null && bucketSize == null) { + if (!StringUtils.hasText(name) && min == null && max == null && bucketSize == null) { return null; } DBObject dbo = new BasicDBObject(); - if (name != null) { + if (StringUtils.hasText(name)) { dbo.put("name", name); } @@ -187,6 +185,7 @@ public class GeospatialIndex implements IndexDefinition { } break; } + return dbo; } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/Index.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/Index.java index 73c7b454b..a737a9af9 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/Index.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/Index.java @@ -22,6 +22,7 @@ import java.util.concurrent.TimeUnit; import org.springframework.data.domain.Sort.Direction; import org.springframework.data.mongodb.core.query.Order; import org.springframework.util.Assert; +import org.springframework.util.StringUtils; import com.mongodb.BasicDBObject; import com.mongodb.DBObject; @@ -174,12 +175,8 @@ public class Index implements IndexDefinition { public DBObject getIndexOptions() { - if (name == null && !unique) { - return null; - } - DBObject dbo = new BasicDBObject(); - if (name != null) { + if (StringUtils.hasText(name)) { dbo.put("name", name); } if (unique) { @@ -197,6 +194,7 @@ public class Index implements IndexDefinition { if (expire >= 0) { dbo.put("expireAfterSeconds", expire); } + return dbo; } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/Indexed.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/Indexed.java index 65838c54e..73aaeb15e 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/Indexed.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/Indexed.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2013 the original author or authors. + * Copyright 2011-2014 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. @@ -27,6 +27,7 @@ import java.lang.annotation.Target; * @author Oliver Gierke * @author Philipp Schneider * @author Johno Crawford + * @author Thomas Darimont */ @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) @@ -63,6 +64,15 @@ public @interface Indexed { */ String name() default ""; + /** + * If set to {@literal true} then MongoDB will ignore the given index name and instead generate a new name. Defaults + * to {@literal false}. + * + * @return + * @since 1.5 + */ + boolean useGeneratedName() default false; + /** * Colleciton name for index to be created on. * diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexResolver.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexResolver.java index 29b3ed8e9..1e51bad66 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexResolver.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexResolver.java @@ -186,7 +186,9 @@ public class MongoPersistentEntityIndexResolver implements IndexResolver { String collection = StringUtils.hasText(index.collection()) ? index.collection() : fallbackCollection; CompoundIndexDefinition indexDefinition = new CompoundIndexDefinition((DBObject) JSON.parse(index.def())); - indexDefinition.named(index.name()); + if (!index.useGeneratedName()) { + indexDefinition.named(index.name()); + } if (index.unique()) { indexDefinition.unique(index.dropDups() ? Duplicates.DROP : Duplicates.RETAIN); } @@ -222,7 +224,11 @@ public class MongoPersistentEntityIndexResolver implements IndexResolver { String collection = StringUtils.hasText(index.collection()) ? index.collection() : fallbackCollection; Index indexDefinition = new Index(); - indexDefinition.named(StringUtils.hasText(index.name()) ? index.name() : persitentProperty.getFieldName()); + + if (!index.useGeneratedName()) { + indexDefinition.named(StringUtils.hasText(index.name()) ? index.name() : persitentProperty.getFieldName()); + } + indexDefinition.on(persitentProperty.getFieldName(), IndexDirection.ASCENDING.equals(index.direction()) ? Sort.Direction.ASC : Sort.Direction.DESC); @@ -260,7 +266,11 @@ public class MongoPersistentEntityIndexResolver implements IndexResolver { GeospatialIndex indexDefinition = new GeospatialIndex(dotPath); indexDefinition.withBits(index.bits()); indexDefinition.withMin(index.min()).withMax(index.max()); - indexDefinition.named(StringUtils.hasText(index.name()) ? index.name() : persistentProperty.getName()); + + if (!index.useGeneratedName()) { + indexDefinition.named(StringUtils.hasText(index.name()) ? index.name() : persistentProperty.getName()); + } + indexDefinition.typed(index.type()).withBucketSize(index.bucketSize()).withAdditionalField(index.additionalField()); return new IndexDefinitionHolder(dotPath, indexDefinition, collection); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/geo/GeoSpatialIndexTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/geo/GeoSpatialIndexTests.java index c84ce35b2..1c2f0a683 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/geo/GeoSpatialIndexTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/geo/GeoSpatialIndexTests.java @@ -15,9 +15,10 @@ */ package org.springframework.data.mongodb.core.geo; -import static org.hamcrest.CoreMatchers.*; +import static org.hamcrest.Matchers.*; import static org.junit.Assert.*; +import java.util.List; import java.util.Map; import org.junit.Before; @@ -27,10 +28,12 @@ import org.springframework.dao.DataAccessException; import org.springframework.data.geo.Point; import org.springframework.data.mongodb.config.AbstractIntegrationTests; import org.springframework.data.mongodb.core.CollectionCallback; +import org.springframework.data.mongodb.core.IndexOperations; import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.core.WriteResultChecking; import org.springframework.data.mongodb.core.index.GeoSpatialIndexType; import org.springframework.data.mongodb.core.index.GeoSpatialIndexed; +import org.springframework.data.mongodb.core.index.IndexInfo; import org.springframework.data.mongodb.core.mapping.Document; import com.mongodb.DBCollection; @@ -99,6 +102,29 @@ public class GeoSpatialIndexTests extends AbstractIntegrationTests { } } + /** + * @see DATAMONGO-827 + */ + @Test + public void useGeneratedNameShouldGenerateAnIndexName() { + + try { + + GeoSpatialEntity2dWithGeneratedIndex geo = new GeoSpatialEntity2dWithGeneratedIndex(45.2, 4.6); + template.save(geo); + + IndexOperations indexOps = template.indexOps(GeoSpatialEntity2dWithGeneratedIndex.class); + List indexInfo = indexOps.getIndexInfo(); + + assertThat(indexInfo, hasSize(2)); + assertThat(indexInfo.get(1), is(notNullValue())); + assertThat(indexInfo.get(1).getName(), is("location_2d")); + + } finally { + template.dropCollection(GeoSpatialEntity2D.class); + } + } + /** * Returns whether an index with the given name exists for the given entity type. * @@ -168,4 +194,15 @@ public class GeoSpatialIndexTests extends AbstractIntegrationTests { this.location.coordinates = new double[] { x, y }; } } + + @Document + static class GeoSpatialEntity2dWithGeneratedIndex { + + public String id; + @GeoSpatialIndexed(type = GeoSpatialIndexType.GEO_2D, useGeneratedName = true) public Point location; + + public GeoSpatialEntity2dWithGeneratedIndex(double x, double y) { + this.location = new Point(x, y); + } + } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexCreatorUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexCreatorUnitTests.java index bc8b33645..7a95af7c6 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexCreatorUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexCreatorUnitTests.java @@ -51,6 +51,7 @@ import com.mongodb.DBObject; * @author Philipp Schneider * @author Johno Crawford * @author Christoph Strobl + * @author Thomas Darimont */ @RunWith(MockitoJUnitRunner.class) public class MongoPersistentEntityIndexCreatorUnitTests { @@ -166,6 +167,20 @@ public class MongoPersistentEntityIndexCreatorUnitTests { .add("max", 180).add("bits", 26).get())); } + /** + * @see DATAMONGO-827 + */ + @Test + public void autoGeneratedIndexNameShouldGenerateNoName() { + + MongoMappingContext mappingContext = prepareMappingContext(EntityWithGeneratedIndexName.class); + new MongoPersistentEntityIndexCreator(mappingContext, factory); + + assertThat(keysCaptor.getValue().containsField("name"), is(false)); + assertThat(keysCaptor.getValue().keySet(), hasItem("lastname")); + assertThat(optionsCaptor.getValue(), is(new BasicDBObjectBuilder().get())); + } + private static MongoMappingContext prepareMappingContext(Class type) { MongoMappingContext mappingContext = new MongoMappingContext(); @@ -217,4 +232,10 @@ public class MongoPersistentEntityIndexCreatorUnitTests { @GeoSpatialIndexed Point location; } + + @Document + class EntityWithGeneratedIndexName { + + @Indexed(useGeneratedName = true, name = "ignored") String lastname; + } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexResolverUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexResolverUnitTests.java index 1639488c3..6fa033b7a 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexResolverUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexResolverUnitTests.java @@ -310,6 +310,23 @@ public class MongoPersistentEntityIndexResolverUnitTests { assertThat(indexDefinition.getIndexKeys(), equalTo(new BasicDBObjectBuilder().add("foo", 1).add("bar", -1).get())); } + /** + * @see DATAMONGO-827 + */ + @Test + public void compoundIndexDoesNotSpecifyNameWhenUsingGenerateName() { + + List indexDefinitions = prepareMappingContextAndResolveIndexForType(ComountIndexWithAutogeneratedName.class); + + IndexDefinition indexDefinition = indexDefinitions.get(0).getIndexDefinition(); + assertThat( + indexDefinition.getIndexOptions(), + equalTo(new BasicDBObjectBuilder().add("unique", true).add("dropDups", true).add("sparse", true) + .add("background", true).add("expireAfterSeconds", 10L).get())); + assertThat(indexDefinition.getIndexKeys(), equalTo(new BasicDBObjectBuilder().add("foo", 1).add("bar", -1).get())); + + } + @Document(collection = "CompoundIndexOnLevelZero") @CompoundIndexes({ @CompoundIndex(name = "compound_index", def = "{'foo': 1, 'bar': -1}", background = true, dropDups = true, expireAfterSeconds = 10, sparse = true, unique = true) }) @@ -318,6 +335,13 @@ public class MongoPersistentEntityIndexResolverUnitTests { static class IndexDefinedOnSuperClass extends CompoundIndexOnLevelZero { } + + @Document(collection = "ComountIndexWithAutogeneratedName") + @CompoundIndexes({ @CompoundIndex(useGeneratedName = true, def = "{'foo': 1, 'bar': -1}", background = true, + dropDups = true, expireAfterSeconds = 10, sparse = true, unique = true) }) + static class ComountIndexWithAutogeneratedName { + + } } public static class MixedIndexResolutionTests {