DATAMONGO-827 - Allow index creation use mongodb auto generated names.
We now support letting MongoDB generate index names by introducing the attribute "useGeneratedName" to the @Indexed, @GeoSpatialIndex, @CompoundIndex annotations.
This commit is contained in:
committed by
Oliver Gierke
parent
af8a53bef6
commit
65497f93d4
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<IndexDefinitionHolder> 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 {
|
||||
|
||||
Reference in New Issue
Block a user