diff --git a/pom.xml b/pom.xml
index 657607148e..7aad355338 100644
--- a/pom.xml
+++ b/pom.xml
@@ -5,7 +5,7 @@
org.springframework.data
spring-data-mongodb-parent
- 2.2.0.BUILD-SNAPSHOT
+ 2.2.0.DATAMONGO-2188-SNAPSHOT
pom
Spring Data MongoDB
diff --git a/spring-data-mongodb-benchmarks/pom.xml b/spring-data-mongodb-benchmarks/pom.xml
index c2ff37b35c..fcbec2ec6b 100644
--- a/spring-data-mongodb-benchmarks/pom.xml
+++ b/spring-data-mongodb-benchmarks/pom.xml
@@ -7,7 +7,7 @@
org.springframework.data
spring-data-mongodb-parent
- 2.2.0.BUILD-SNAPSHOT
+ 2.2.0.DATAMONGO-2188-SNAPSHOT
../pom.xml
diff --git a/spring-data-mongodb-cross-store/pom.xml b/spring-data-mongodb-cross-store/pom.xml
index fd36f227c0..6d93c83777 100644
--- a/spring-data-mongodb-cross-store/pom.xml
+++ b/spring-data-mongodb-cross-store/pom.xml
@@ -6,7 +6,7 @@
org.springframework.data
spring-data-mongodb-parent
- 2.2.0.BUILD-SNAPSHOT
+ 2.2.0.DATAMONGO-2188-SNAPSHOT
../pom.xml
@@ -50,7 +50,7 @@
org.springframework.data
spring-data-mongodb
- 2.2.0.BUILD-SNAPSHOT
+ 2.2.0.DATAMONGO-2188-SNAPSHOT
diff --git a/spring-data-mongodb-distribution/pom.xml b/spring-data-mongodb-distribution/pom.xml
index fc8d28a2b6..4ce4ddb459 100644
--- a/spring-data-mongodb-distribution/pom.xml
+++ b/spring-data-mongodb-distribution/pom.xml
@@ -14,7 +14,7 @@
org.springframework.data
spring-data-mongodb-parent
- 2.2.0.BUILD-SNAPSHOT
+ 2.2.0.DATAMONGO-2188-SNAPSHOT
../pom.xml
diff --git a/spring-data-mongodb/pom.xml b/spring-data-mongodb/pom.xml
index f3c85a046a..cbe8c93229 100644
--- a/spring-data-mongodb/pom.xml
+++ b/spring-data-mongodb/pom.xml
@@ -11,7 +11,7 @@
org.springframework.data
spring-data-mongodb-parent
- 2.2.0.BUILD-SNAPSHOT
+ 2.2.0.DATAMONGO-2188-SNAPSHOT
../pom.xml
diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoConfigurationSupport.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoConfigurationSupport.java
index d6562f75fd..bb8406e384 100644
--- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoConfigurationSupport.java
+++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoConfigurationSupport.java
@@ -87,6 +87,7 @@ public MongoMappingContext mongoMappingContext() throws ClassNotFoundException {
mappingContext.setInitialEntitySet(getInitialEntitySet());
mappingContext.setSimpleTypeHolder(customConversions().getSimpleTypeHolder());
mappingContext.setFieldNamingStrategy(fieldNamingStrategy());
+ mappingContext.setAutoIndexCreation(autoIndexCreation());
return mappingContext;
}
@@ -190,4 +191,16 @@ protected FieldNamingStrategy fieldNamingStrategy() {
return abbreviateFieldNames() ? new CamelCaseAbbreviatingFieldNamingStrategy()
: PropertyNameFieldNamingStrategy.INSTANCE;
}
+
+ /**
+ * Configure whether to automatically create indices for domain types by deriving the
+ * {@link org.springframework.data.mongodb.core.index.IndexDefinition} from the entity or not.
+ *
+ * @return {@literal true} by default.
+ * INFO: As of 3.x the default will be set to {@literal false}.
+ * @since 2.2
+ */
+ protected boolean autoIndexCreation() {
+ return true;
+ }
}
diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoTemplate.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoTemplate.java
index 13c2606e3e..94fe71d4ca 100644
--- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoTemplate.java
+++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoTemplate.java
@@ -246,10 +246,14 @@ public MongoTemplate(MongoDbFactory mongoDbFactory, @Nullable MongoConverter mon
mappingContext = this.mongoConverter.getMappingContext();
// We create indexes based on mapping events
if (mappingContext instanceof MongoMappingContext) {
- indexCreator = new MongoPersistentEntityIndexCreator((MongoMappingContext) mappingContext, this);
- eventPublisher = new MongoMappingEventPublisher(indexCreator);
- if (mappingContext instanceof ApplicationEventPublisherAware) {
- ((ApplicationEventPublisherAware) mappingContext).setApplicationEventPublisher(eventPublisher);
+
+ MongoMappingContext mappingContext = (MongoMappingContext) this.mappingContext;
+
+ if (mappingContext.isAutoIndexCreation()) {
+
+ indexCreator = new MongoPersistentEntityIndexCreator(mappingContext, this);
+ eventPublisher = new MongoMappingEventPublisher(indexCreator);
+ mappingContext.setApplicationEventPublisher(eventPublisher);
}
}
}
@@ -1582,7 +1586,8 @@ public UpdateResult doInCollection(MongoCollection collection)
query.getCollation().map(Collation::toMongoCollation).ifPresent(opts::collation);
}
- Document updateObj = update instanceof MappedUpdate ? update.getUpdateObject() : updateMapper.getMappedObject(update.getUpdateObject(), entity);
+ Document updateObj = update instanceof MappedUpdate ? update.getUpdateObject()
+ : updateMapper.getMappedObject(update.getUpdateObject(), entity);
if (multi && update.isIsolated() && !queryObj.containsKey("$isolated")) {
queryObj.put("$isolated", 1);
@@ -1617,7 +1622,8 @@ public UpdateResult doInCollection(MongoCollection collection)
});
}
- private void increaseVersionForUpdateIfNecessary(@Nullable MongoPersistentEntity> persistentEntity, UpdateDefinition update) {
+ private void increaseVersionForUpdateIfNecessary(@Nullable MongoPersistentEntity> persistentEntity,
+ UpdateDefinition update) {
if (persistentEntity != null && persistentEntity.hasVersionProperty()) {
String versionFieldName = persistentEntity.getRequiredVersionProperty().getFieldName();
diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java
index 3e32f780b8..640f449cd6 100644
--- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java
+++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java
@@ -232,12 +232,15 @@ public ReactiveMongoTemplate(ReactiveMongoDatabaseFactory mongoDatabaseFactory,
if (this.mappingContext instanceof MongoMappingContext) {
MongoMappingContext mongoMappingContext = (MongoMappingContext) this.mappingContext;
- this.indexCreator = new ReactiveMongoPersistentEntityIndexCreator(mongoMappingContext, this::indexOps);
- this.eventPublisher = new MongoMappingEventPublisher(this.indexCreatorListener);
- mongoMappingContext.setApplicationEventPublisher(this.eventPublisher);
- this.mappingContext.getPersistentEntities()
- .forEach(entity -> onCheckForIndexes(entity, subscriptionExceptionHandler));
+ if (mongoMappingContext.isAutoIndexCreation()) {
+ this.indexCreator = new ReactiveMongoPersistentEntityIndexCreator(mongoMappingContext, this::indexOps);
+ this.eventPublisher = new MongoMappingEventPublisher(this.indexCreatorListener);
+
+ mongoMappingContext.setApplicationEventPublisher(this.eventPublisher);
+ this.mappingContext.getPersistentEntities()
+ .forEach(entity -> onCheckForIndexes(entity, subscriptionExceptionHandler));
+ }
}
}
@@ -3182,6 +3185,7 @@ public void onApplicationEvent(MappingContextEvent, ?> event) {
// Double check type as Spring infrastructure does not consider nested generics
if (entity instanceof MongoPersistentEntity) {
+
onCheckForIndexes((MongoPersistentEntity>) entity, subscriptionExceptionHandler);
}
}
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 3395da3bd5..2cac65a39b 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
@@ -55,7 +55,8 @@
/**
* @return
- * @see https://docs.mongodb.org/manual/core/index-unique/
+ * @see https://docs.mongodb.org/manual/core/index-unique/
*/
boolean unique() default false;
@@ -63,13 +64,15 @@
* If set to true index will skip over any document that is missing the indexed field.
*
* @return
- * @see https://docs.mongodb.org/manual/core/index-sparse/
+ * @see https://docs.mongodb.org/manual/core/index-sparse/
*/
boolean sparse() default false;
/**
* @return
- * @see https://docs.mongodb.org/manual/core/index-creation/#index-creation-duplicate-dropping
+ * @see https://docs.mongodb.org/manual/core/index-creation/#index-creation-duplicate-dropping
* @deprecated since 2.1. No longer supported by MongoDB as of server version 3.0.
*/
@Deprecated
@@ -131,7 +134,8 @@
* If {@literal true} the index will be created in the background.
*
* @return
- * @see https://docs.mongodb.org/manual/core/indexes/#background-construction
+ * @see https://docs.mongodb.org/manual/core/indexes/#background-construction
*/
boolean background() default false;
diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexResolver.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexResolver.java
index c1c87ea2a8..0bc0bedc92 100644
--- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexResolver.java
+++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexResolver.java
@@ -15,25 +15,53 @@
*/
package org.springframework.data.mongodb.core.index;
-import org.springframework.data.mongodb.core.index.MongoPersistentEntityIndexResolver.IndexDefinitionHolder;
+import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
+import org.springframework.data.util.ClassTypeInformation;
import org.springframework.data.util.TypeInformation;
+import org.springframework.util.Assert;
/**
* {@link IndexResolver} finds those {@link IndexDefinition}s to be created for a given class.
*
* @author Christoph Strobl
* @author Thomas Darimont
+ * @author Mark Paluch
* @since 1.5
*/
-interface IndexResolver {
+public interface IndexResolver {
/**
- * Find and create {@link IndexDefinition}s for properties of given {@link TypeInformation}. {@link IndexDefinition}s are created
- * for properties and types with {@link Indexed}, {@link CompoundIndexes} or {@link GeoSpatialIndexed}.
+ * Creates a new {@link IndexResolver} given {@link MongoMappingContext}.
+ *
+ * @param mappingContext must not be {@literal null}.
+ * @return the new {@link IndexResolver}.
+ */
+ static IndexResolver create(MongoMappingContext mappingContext) {
+
+ Assert.notNull(mappingContext, "MongoMappingContext must not be null!");
+
+ return new MongoPersistentEntityIndexResolver(mappingContext);
+ }
+
+ /**
+ * Find and create {@link IndexDefinition}s for properties of given {@link TypeInformation}. {@link IndexDefinition}s
+ * are created for properties and types with {@link Indexed}, {@link CompoundIndexes} or {@link GeoSpatialIndexed}.
*
* @param typeInformation
* @return Empty {@link Iterable} in case no {@link IndexDefinition} could be resolved for type.
*/
- Iterable extends IndexDefinitionHolder> resolveIndexFor(TypeInformation> typeInformation);
+ Iterable extends IndexDefinition> resolveIndexFor(TypeInformation> typeInformation);
+
+ /**
+ * Find and create {@link IndexDefinition}s for properties of given {@link TypeInformation}. {@link IndexDefinition}s
+ * are created for properties and types with {@link Indexed}, {@link CompoundIndexes} or {@link GeoSpatialIndexed}.
+ *
+ * @param entityType
+ * @return Empty {@link Iterable} in case no {@link IndexDefinition} could be resolved for type.
+ * @see 2.2
+ */
+ default Iterable extends IndexDefinition> resolveIndexFor(Class> entityType) {
+ return resolveIndexFor(ClassTypeInformation.from(entityType));
+ }
}
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 5ecb62d200..d0b2535346 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
@@ -31,7 +31,7 @@
* @author Christoph Strobl
* @author Jordi Llach
*/
-@Target({ElementType.ANNOTATION_TYPE, ElementType.FIELD})
+@Target({ ElementType.ANNOTATION_TYPE, ElementType.FIELD })
@Retention(RetentionPolicy.RUNTIME)
public @interface Indexed {
@@ -39,7 +39,8 @@
* If set to true reject all documents that contain a duplicate value for the indexed field.
*
* @return
- * @see https://docs.mongodb.org/manual/core/index-unique/
+ * @see https://docs.mongodb.org/manual/core/index-unique/
*/
boolean unique() default false;
@@ -49,13 +50,15 @@
* If set to true index will skip over any document that is missing the indexed field.
*
* @return
- * @see https://docs.mongodb.org/manual/core/index-sparse/
+ * @see https://docs.mongodb.org/manual/core/index-sparse/
*/
boolean sparse() default false;
/**
* @return
- * @see https://docs.mongodb.org/manual/core/index-creation/#index-creation-duplicate-dropping
+ * @see https://docs.mongodb.org/manual/core/index-creation/#index-creation-duplicate-dropping
* @deprecated since 2.1. No longer supported by MongoDB as of server version 3.0.
*/
@Deprecated
@@ -115,7 +118,8 @@
* If {@literal true} the index will be created in the background.
*
* @return
- * @see https://docs.mongodb.org/manual/core/indexes/#background-construction
+ * @see https://docs.mongodb.org/manual/core/indexes/#background-construction
*/
boolean background() default false;
@@ -123,7 +127,8 @@
* Configures the number of seconds after which the collection should expire. Defaults to -1 for no expiry.
*
* @return
- * @see https://docs.mongodb.org/manual/tutorial/expire-data/
+ * @see https://docs.mongodb.org/manual/tutorial/expire-data/
*/
int expireAfterSeconds() default -1;
}
diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/JustOnceLogger.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/JustOnceLogger.java
new file mode 100644
index 0000000000..8b172b007a
--- /dev/null
+++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/JustOnceLogger.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2019 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.mongodb.core.index;
+
+import java.util.Collections;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentSkipListSet;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * @author Christoph Strobl
+ * @since 2.2
+ */
+class JustOnceLogger {
+
+ private static final Map> KNOWN_LOGS = new ConcurrentHashMap<>();
+ private static final String AUTO_INDEX_CREATION_CONFIG_CHANGE;
+
+ static {
+ AUTO_INDEX_CREATION_CONFIG_CHANGE = "Automatic index creation will be disabled by default as of Spring Data MongoDB 3.x."
+ + System.lineSeparator()
+ + "\tPlease use 'MongoMappingContext#setAutoIndexCreation(boolean)' or override 'MongoConfigurationSupport#autoIndexCreation()' to be explicit."
+ + System.lineSeparator()
+ + "\tHowever, we recommend setting up indices manually in an application ready block. You may use index derivation there as well."
+ + System.lineSeparator() + System.lineSeparator() //
+ + "\t> -----------------------------------------------------------------------------------------"
+ + System.lineSeparator() //
+ + "\t> @EventListener(ApplicationReadyEvent.class)" + System.lineSeparator() //
+ + "\t> public void initIndicesAfterStartup() {" + System.lineSeparator() //
+ + "\t>" + System.lineSeparator() //
+ + "\t> IndexOperations indexOps = mongoTemplate.indexOps(DomainType.class);" + System.lineSeparator()//
+ + "\t>" + System.lineSeparator() //
+ + "\t> IndexResolver resolver = new MongoPersistentEntityIndexResolver(mongoMappingContext);"
+ + System.lineSeparator() //
+ + "\t> resolver.resolveIndexFor(DomainType.class).forEach(indexOps::ensureIndex);" + System.lineSeparator() //
+ + "\t> }" + System.lineSeparator() //
+ + "\t> -----------------------------------------------------------------------------------------"
+ + System.lineSeparator();
+ }
+
+ static void logWarnIndexCreationConfigurationChange(String loggerName) {
+ warnOnce(loggerName, AUTO_INDEX_CREATION_CONFIG_CHANGE);
+ }
+
+ static void warnOnce(String loggerName, String message) {
+
+ Logger logger = LoggerFactory.getLogger(loggerName);
+ if (!logger.isWarnEnabled()) {
+ return;
+ }
+
+ if (!KNOWN_LOGS.containsKey(loggerName)) {
+
+ KNOWN_LOGS.put(loggerName, new ConcurrentSkipListSet<>(Collections.singleton(message)));
+ logger.warn(message);
+ } else {
+
+ Set messages = KNOWN_LOGS.get(loggerName);
+ if (messages.contains(message)) {
+ return;
+ }
+
+ messages.add(message);
+ logger.warn(message);
+ }
+ }
+}
diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexCreator.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexCreator.java
index c4a7f3f608..223a625b2e 100644
--- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexCreator.java
+++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexCreator.java
@@ -63,11 +63,13 @@ public class MongoPersistentEntityIndexCreator implements ApplicationListener event) {
// Double check type as Spring infrastructure does not consider nested generics
if (entity instanceof MongoPersistentEntity) {
+
checkForIndexes((MongoPersistentEntity>) entity);
}
}
@@ -131,8 +134,16 @@ private void checkForIndexes(final MongoPersistentEntity> entity) {
private void checkForAndCreateIndexes(MongoPersistentEntity> entity) {
if (entity.isAnnotationPresent(Document.class)) {
- for (IndexDefinitionHolder indexToCreate : indexResolver.resolveIndexFor(entity.getTypeInformation())) {
+ for (IndexDefinition indexDefinition : indexResolver.resolveIndexFor(entity.getTypeInformation())) {
+
+ JustOnceLogger.logWarnIndexCreationConfigurationChange(this.getClass().getName());
+
+ IndexDefinitionHolder indexToCreate = indexDefinition instanceof IndexDefinitionHolder
+ ? (IndexDefinitionHolder) indexDefinition
+ : new IndexDefinitionHolder("", indexDefinition, entity.getCollection());
+
createIndex(indexToCreate);
+
}
}
}
@@ -146,8 +157,8 @@ void createIndex(IndexDefinitionHolder indexDefinition) {
} catch (UncategorizedMongoDbException ex) {
- if (ex.getCause() instanceof MongoException &&
- MongoDbErrorCodes.isDataIntegrityViolationCode(((MongoException) ex.getCause()).getCode())) {
+ if (ex.getCause() instanceof MongoException
+ && MongoDbErrorCodes.isDataIntegrityViolationCode(((MongoException) ex.getCause()).getCode())) {
IndexInfo existingIndex = fetchIndexInformation(indexDefinition);
String message = "Cannot create index for '%s' in collection '%s' with keys '%s' and options '%s'.";
diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/ReactiveMongoPersistentEntityIndexCreator.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/ReactiveMongoPersistentEntityIndexCreator.java
index 813a8a5040..c8561fd9c2 100644
--- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/ReactiveMongoPersistentEntityIndexCreator.java
+++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/ReactiveMongoPersistentEntityIndexCreator.java
@@ -63,7 +63,7 @@ public class ReactiveMongoPersistentEntityIndexCreator {
*/
public ReactiveMongoPersistentEntityIndexCreator(MongoMappingContext mappingContext,
ReactiveIndexOperationsProvider operationsProvider) {
- this(mappingContext, operationsProvider, new MongoPersistentEntityIndexResolver(mappingContext));
+ this(mappingContext, operationsProvider, IndexResolver.create(mappingContext));
}
/**
@@ -125,7 +125,12 @@ private Mono checkForAndCreateIndexes(MongoPersistentEntity> entity) {
List> publishers = new ArrayList<>();
if (entity.isAnnotationPresent(Document.class)) {
- for (IndexDefinitionHolder indexToCreate : indexResolver.resolveIndexFor(entity.getTypeInformation())) {
+ for (IndexDefinition indexDefinition : indexResolver.resolveIndexFor(entity.getTypeInformation())) {
+
+ IndexDefinitionHolder indexToCreate = indexDefinition instanceof IndexDefinitionHolder
+ ? (IndexDefinitionHolder) indexDefinition
+ : new IndexDefinitionHolder("", indexDefinition, entity.getCollection());
+
publishers.add(createIndex(indexToCreate));
}
}
@@ -135,6 +140,8 @@ private Mono checkForAndCreateIndexes(MongoPersistentEntity> entity) {
Mono createIndex(IndexDefinitionHolder indexDefinition) {
+ JustOnceLogger.logWarnIndexCreationConfigurationChange(this.getClass().getName());
+
return operationsProvider.indexOps(indexDefinition.getCollection()).ensureIndex(indexDefinition) //
.onErrorResume(ReactiveMongoPersistentEntityIndexCreator::isDataIntegrityViolation,
e -> translateException(e, indexDefinition));
diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoMappingContext.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoMappingContext.java
index 49a3d5a942..0c82b70a62 100644
--- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoMappingContext.java
+++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoMappingContext.java
@@ -43,6 +43,7 @@ public class MongoMappingContext extends AbstractMappingContext
+ * NOTE:Index creation should happen at a well-defined time that is ideally controlled by the
+ * application itself.
+ *
+ * @return {@literal true} when auto-index creation is enabled; {@literal false} otherwise.
+ * @since 2.2
+ * @see org.springframework.data.mongodb.core.index.Indexed
+ */
+ public boolean isAutoIndexCreation() {
+ return autoIndexCreation;
+ }
+
+ /**
+ * Enables/disables auto-index creation.
+ * NOTE:Index creation should happen at a well-defined time that is ideally controlled by the
+ * application itself.
+ *
+ * @param autoCreateIndexes set to {@literal false} to disable auto-index creation.
+ * @since 2.2
+ * @see org.springframework.data.mongodb.core.index.Indexed
+ */
+ public void setAutoIndexCreation(boolean autoCreateIndexes) {
+ this.autoIndexCreation = autoCreateIndexes;
+ }
}
diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/IndexingIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/IndexingIntegrationTests.java
index de4d6d52de..32b7acd6b5 100644
--- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/IndexingIntegrationTests.java
+++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/IndexingIntegrationTests.java
@@ -30,25 +30,26 @@
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ConfigurableApplicationContext;
-import org.springframework.dao.DataAccessException;
+import org.springframework.data.mongodb.MongoCollectionUtils;
import org.springframework.data.mongodb.MongoDbFactory;
-import org.springframework.data.mongodb.core.CollectionCallback;
import org.springframework.data.mongodb.core.MongoOperations;
+import org.springframework.data.mongodb.core.MongoTemplate;
+import org.springframework.data.mongodb.core.convert.MappingMongoConverter;
+import org.springframework.data.mongodb.core.convert.NoOpDbRefResolver;
import org.springframework.data.mongodb.core.mapping.Document;
import org.springframework.data.mongodb.core.mapping.Field;
+import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
-import com.mongodb.MongoException;
-import com.mongodb.client.MongoCollection;
-
/**
* Integration tests for index handling.
*
* @author Oliver Gierke
* @author Christoph Strobl
* @author Jordi Llach
+ * @author Mark Paluch
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:infrastructure.xml")
@@ -72,6 +73,21 @@ public void createsIndexWithFieldName() {
assertThat(hasIndex("_firstname", IndexedPerson.class), is(true));
}
+ @Test // DATAMONGO-2188
+ @DirtiesContext
+ public void shouldNotCreateIndexOnIndexingDisabled() {
+
+ MongoMappingContext context = new MongoMappingContext();
+ context.setAutoIndexCreation(false);
+
+ MongoTemplate template = new MongoTemplate(mongoDbFactory,
+ new MappingMongoConverter(NoOpDbRefResolver.INSTANCE, context));
+
+ template.getConverter().getMappingContext().getPersistentEntity(IndexedPerson.class);
+
+ assertThat(hasIndex("_firstname", MongoCollectionUtils.getPreferredCollectionName(IndexedPerson.class)), is(false));
+ }
+
@Test // DATAMONGO-1163
@DirtiesContext
public void createsIndexFromMetaAnnotation() {
@@ -101,22 +117,30 @@ class IndexedPerson {
* @param entityType
* @return
*/
- private boolean hasIndex(final String indexName, Class> entityType) {
+ private boolean hasIndex(String indexName, Class> entityType) {
+ return hasIndex(indexName, operations.getCollectionName(entityType));
+ }
+
+ /**
+ * Returns whether an index with the given name exists for the given collection.
+ *
+ * @param indexName
+ * @param collectionName
+ * @return
+ */
+ private boolean hasIndex(String indexName, String collectionName) {
- return operations.execute(entityType, new CollectionCallback() {
- public Boolean doInCollection(MongoCollection collection)
- throws MongoException, DataAccessException {
+ return operations.execute(collectionName, collection -> {
- List indexes = new ArrayList();
- collection.listIndexes(org.bson.Document.class).into(indexes);
+ List indexes = new ArrayList<>();
+ collection.listIndexes(org.bson.Document.class).into(indexes);
- for (org.bson.Document indexInfo : indexes) {
- if (indexName.equals(indexInfo.get("name"))) {
- return true;
- }
+ for (org.bson.Document indexInfo : indexes) {
+ if (indexName.equals(indexInfo.get("name"))) {
+ return true;
}
- return false;
}
+ return false;
});
}
}
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 9f1cea4ecb..4c0e4576eb 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
@@ -64,6 +64,7 @@ public class MongoPersistentEntityIndexResolverUnitTests {
* Test resolution of {@link Indexed}.
*
* @author Christoph Strobl
+ * @author Mark Paluch
*/
public static class IndexResolutionTests {
@@ -87,7 +88,17 @@ public void indexPathOnLevelOneIsResolvedCorrectly() {
}
@Test // DATAMONGO-899
- public void depplyNestedIndexPathIsResolvedCorrectly() {
+ public void shouldResolveIndexViaClass() {
+
+ MongoMappingContext mappingContext = new MongoMappingContext();
+ IndexResolver indexResolver = IndexResolver.create(mappingContext);
+ Iterable extends IndexDefinition> definitions = indexResolver.resolveIndexFor(IndexOnLevelOne.class);
+
+ assertThat(definitions.iterator().hasNext(), is(true));
+ }
+
+ @Test // DATAMONGO-899
+ public void deeplyNestedIndexPathIsResolvedCorrectly() {
List indexDefinitions = prepareMappingContextAndResolveIndexForType(IndexOnLevelTwo.class);
diff --git a/src/main/asciidoc/reference/mapping.adoc b/src/main/asciidoc/reference/mapping.adoc
index 706d4ec070..05e2e63cf7 100644
--- a/src/main/asciidoc/reference/mapping.adoc
+++ b/src/main/asciidoc/reference/mapping.adoc
@@ -377,8 +377,29 @@ public class Person {
====
IMPORTANT: The `@Id` annotation tells the mapper which property you want to use for the MongoDB `_id` property, and the `@Indexed` annotation tells the mapping framework to call `createIndex(…)` on that property of your document, making searches faster.
+Automatic index creation is only done for types annotated with `@Document`.
-IMPORTANT: Automatic index creation is only done for types annotated with `@Document`.
+[NOTE]
+====
+To turn automatic index creation _OFF_ please override `autoIndexCreation()` in your configuration.
+[source,java]
+----
+@Configuration
+public class Config extends AbstractMongoClientConfiguration {
+
+ @Override
+ public boolean autoIndexCreation() {
+ return false;
+ }
+
+ // ...
+}
+----
+====
+
+IMPORTANT: Automatic index creation will be turned _OFF_ by default with the release of 3.x.
+We recommend index creation to happen either out of band or as part of the application startup using
+`IndexOperations`. We'll once add a `WARN` to your log when we encounter automatic index creation.
[[mapping-usage-annotations]]
=== Mapping Annotation Overview