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 70dec098c..d8693e804 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 @@ -105,6 +105,7 @@ public class Index implements IndexDefinition { * @return this. * @see https://www.mongodb.com/docs/manual/core/index-hidden/ + * @since 4.1 */ public Index hidden() { this.hidden = true; diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexInfo.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexInfo.java index 4c8a9c556..199d98928 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexInfo.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexInfo.java @@ -129,14 +129,15 @@ public class IndexInfo { String name = sourceDocument.get("name").toString(); - boolean unique = sourceDocument.containsKey("unique") ? (Boolean) sourceDocument.get("unique") : false; - boolean sparse = sourceDocument.containsKey("sparse") ? (Boolean) sourceDocument.get("sparse") : false; - String language = sourceDocument.containsKey("default_language") ? (String) sourceDocument.get("default_language") + boolean unique = sourceDocument.get("unique", false); + boolean sparse = sourceDocument.get("sparse", false); + boolean hidden = sourceDocument.getBoolean("hidden", false); + String language = sourceDocument.containsKey("default_language") ? sourceDocument.getString("default_language") : ""; String partialFilter = extractPartialFilterString(sourceDocument); - IndexInfo info = new IndexInfo(indexFields, name, unique, sparse, language); + IndexInfo info = new IndexInfo(indexFields, name, unique, sparse, language, hidden); info.partialFilterExpression = partialFilter; info.collation = sourceDocument.get("collation", Document.class); @@ -150,8 +151,6 @@ public class IndexInfo { info.wildcardProjection = sourceDocument.get("wildcardProjection", Document.class); } - boolean hidden = sourceDocument.containsKey("hidden") ? (Boolean) sourceDocument.get("hidden") : false; - return info; } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultIndexOperationsIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultIndexOperationsIntegrationTests.java index a9a29e55f..7498f6e55 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultIndexOperationsIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultIndexOperationsIntegrationTests.java @@ -173,6 +173,30 @@ public class DefaultIndexOperationsIntegrationTests { assertThat(result).isEqualTo(expected); } + @Test // GH-4348 + void indexShouldNotBeHiddenByDefault() { + + IndexDefinition index = new Index().named("my-index").on("a", Direction.ASC); + + indexOps = new DefaultIndexOperations(template, COLLECTION_NAME, MappingToSameCollection.class); + indexOps.ensureIndex(index); + + IndexInfo info = findAndReturnIndexInfo(indexOps.getIndexInfo(), "my-index"); + assertThat(info.isHidden()).isFalse(); + } + + @Test // GH-4348 + void shouldCreateHiddenIndex() { + + IndexDefinition index = new Index().named("my-hidden-index").on("a", Direction.ASC).hidden(); + + indexOps = new DefaultIndexOperations(template, COLLECTION_NAME, MappingToSameCollection.class); + indexOps.ensureIndex(index); + + IndexInfo info = findAndReturnIndexInfo(indexOps.getIndexInfo(), "my-hidden-index"); + assertThat(info.isHidden()).isTrue(); + } + private IndexInfo findAndReturnIndexInfo(org.bson.Document keys) { return findAndReturnIndexInfo(indexOps.getIndexInfo(), keys); } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultReactiveIndexOperationsTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultReactiveIndexOperationsTests.java index 0d9ee5890..00febfcba 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultReactiveIndexOperationsTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultReactiveIndexOperationsTests.java @@ -164,6 +164,34 @@ public class DefaultReactiveIndexOperationsTests { .verifyComplete(); } + @Test // GH-4348 + void indexShouldNotBeHiddenByDefault() { + + IndexDefinition index = new Index().named("my-index").on("a", Direction.ASC); + + indexOps.ensureIndex(index).then().as(StepVerifier::create).verifyComplete(); + + indexOps.getIndexInfo().filter(this.indexByName("my-index")).as(StepVerifier::create) // + .consumeNextWith(indexInfo -> { + assertThat(indexInfo.isHidden()).isFalse(); + }) // + .verifyComplete(); + } + + @Test // GH-4348 + void shouldCreateHiddenIndex() { + + IndexDefinition index = new Index().named("my-hidden-index").on("a", Direction.ASC).hidden(); + + indexOps.ensureIndex(index).then().as(StepVerifier::create).verifyComplete(); + + indexOps.getIndexInfo().filter(this.indexByName("my-hidden-index")).as(StepVerifier::create) // + .consumeNextWith(indexInfo -> { + assertThat(indexInfo.isHidden()).isTrue(); + }) // + .verifyComplete(); + } + Predicate indexByName(String name) { return indexInfo -> indexInfo.getName().equals(name); } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java index a14732301..9bfbe989b 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java @@ -329,7 +329,7 @@ public class MongoTemplateTests { p2.setAge(40); template.insert(p2); - template.indexOps(Person.class).ensureIndex(new Index().on("age", Direction.DESC).unique().hidden()); + template.indexOps(Person.class).ensureIndex(new Index().on("age", Direction.DESC).unique()); MongoCollection coll = template.getCollection(template.getCollectionName(Person.class)); List indexInfo = new ArrayList<>(); @@ -355,7 +355,6 @@ public class MongoTemplateTests { IndexInfo ii = indexInfoList.get(1); assertThat(ii.isUnique()).isTrue(); assertThat(ii.isSparse()).isFalse(); - assertThat(ii.isHidden()).isTrue(); List indexFields = ii.getIndexFields(); IndexField field = indexFields.get(0); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/IndexInfoUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/IndexInfoUnitTests.java index f410603ea..34dbaea1a 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/IndexInfoUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/IndexInfoUnitTests.java @@ -31,7 +31,7 @@ import org.springframework.data.domain.Sort.Direction; * @author Christoph Strobl * @author Stefan Tirea */ -public class IndexInfoUnitTests { +class IndexInfoUnitTests { static final String ID_INDEX = "{ \"v\" : 2, \"key\" : { \"_id\" : 1 }, \"name\" : \"_id_\", \"ns\" : \"db.collection\" }"; static final String INDEX_WITH_PARTIAL_FILTER = "{ \"v\" : 2, \"key\" : { \"k3y\" : 1 }, \"name\" : \"partial-filter-index\", \"ns\" : \"db.collection\", \"partialFilterExpression\" : { \"quantity\" : { \"$gte\" : 10 } } }"; @@ -39,9 +39,19 @@ public class IndexInfoUnitTests { static final String HASHED_INDEX = "{ \"v\" : 2, \"key\" : { \"score\" : \"hashed\" }, \"name\" : \"score_hashed\", \"ns\" : \"db.collection\" }"; static final String WILDCARD_INDEX = "{ \"v\" : 2, \"key\" : { \"$**\" : 1 }, \"name\" : \"$**_1\", \"wildcardProjection\" : { \"fieldA\" : 0, \"fieldB.fieldC\" : 0 } }"; static final String INDEX_WITH_COLLATION = "{ \"v\" : 2, \"key\" : { \"_id\" : 1 }, \"name\" : \"projectName\", \"collation\": { \"locale\": \"en_US\", \"strength\": 2 } }"; + static final String HIDDEN_INDEX = """ + { + "v" : 2, + "key" : { + "borough" : 1 + }, + "name" : "borough_1", + "hidden" : true + } + """; @Test - public void isIndexForFieldsCorrectly() { + void isIndexForFieldsCorrectly() { IndexField fooField = IndexField.create("foo", Direction.ASC); IndexField barField = IndexField.create("bar", Direction.DESC); @@ -51,29 +61,29 @@ public class IndexInfoUnitTests { } @Test // DATAMONGO-2170 - public void partialFilterExpressionShouldBeNullIfNotSetInSource() { + void partialFilterExpressionShouldBeNullIfNotSetInSource() { assertThat(getIndexInfo(ID_INDEX).getPartialFilterExpression()).isNull(); } @Test // DATAMONGO-2170 - public void partialFilterExpressionShouldMatchSource() { + void partialFilterExpressionShouldMatchSource() { assertThat(Document.parse(getIndexInfo(INDEX_WITH_PARTIAL_FILTER).getPartialFilterExpression())) .isEqualTo(Document.parse("{ \"quantity\" : { \"$gte\" : 10 } }")); } @Test // DATAMONGO-2081 - public void expireAfterIsParsedCorrectly() { + void expireAfterIsParsedCorrectly() { assertThat(getIndexInfo(INDEX_WITH_EXPIRATION_TIME).getExpireAfter()).contains(Duration.ofHours(1)); } @Test // DATAMONGO-2081 - public void expireAfterIsEmptyIfNotSet() { + void expireAfterIsEmptyIfNotSet() { assertThat(getIndexInfo(ID_INDEX).getExpireAfter()).isEmpty(); } @Test // DATAMONGO-1183 - public void readsHashedIndexCorrectly() { + void readsHashedIndexCorrectly() { assertThat(getIndexInfo(HASHED_INDEX).getIndexFields()).containsExactly(IndexField.hashed("score")); } @@ -83,22 +93,29 @@ public class IndexInfoUnitTests { } @Test // GH-3225 - public void identifiesWildcardIndexCorrectly() { + void identifiesWildcardIndexCorrectly() { assertThat(getIndexInfo(WILDCARD_INDEX).isWildcard()).isTrue(); } @Test // GH-3225 - public void readsWildcardIndexProjectionCorrectly() { + void readsWildcardIndexProjectionCorrectly() { assertThat(getIndexInfo(WILDCARD_INDEX).getWildcardProjection()) .contains(new Document("fieldA", 0).append("fieldB.fieldC", 0)); } @Test // GH-3002 - public void collationParsedCorrectly() { + void collationParsedCorrectly() { assertThat(getIndexInfo(INDEX_WITH_COLLATION).getCollation()) .contains(Document.parse("{ \"locale\": \"en_US\", \"strength\": 2 }")); } + @Test // GH-4348 + void hiddenInfoSetCorrectly() { + + assertThat(getIndexInfo(ID_INDEX).isHidden()).isFalse(); + assertThat(getIndexInfo(HIDDEN_INDEX).isHidden()).isTrue(); + } + private static IndexInfo getIndexInfo(String documentJson) { return IndexInfo.indexInfoOf(Document.parse(documentJson)); }