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 ebaa3a96e..8f2199c93 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 @@ -53,7 +53,8 @@ public @interface Indexed { IndexDirection direction() default IndexDirection.ASCENDING; /** - * If set to true index will skip over any document that is missing the indexed field. + * If set to true index will skip over any document that is missing the indexed field.
+ * Must not be used with {@link #partialFilter()}. * * @return {@literal false} by default. * @see + * Must not be used with {@link #sparse() sparse = true}. + * + * @return empty by default. + * @see https://docs.mongodb.com/manual/core/index-partial/ + * @since 3.1 + */ + String partialFilter() default ""; } 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 0c63d6551..aa3578bad 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 @@ -46,6 +46,7 @@ import org.springframework.data.mongodb.core.mapping.BasicMongoPersistentEntity; import org.springframework.data.mongodb.core.mapping.Document; import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity; import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty; +import org.springframework.data.mongodb.util.BsonUtils; import org.springframework.data.spel.EvaluationContextProvider; import org.springframework.data.util.TypeInformation; import org.springframework.expression.EvaluationContext; @@ -474,9 +475,25 @@ public class MongoPersistentEntityIndexResolver implements IndexResolver { } } + if (StringUtils.hasText(index.partialFilter())) { + indexDefinition.partial(evaluatePartialFilter(index.partialFilter(), persistentProperty.getOwner())); + } + return new IndexDefinitionHolder(dotPath, indexDefinition, collection); } + private PartialIndexFilter evaluatePartialFilter(String filterExpression, PersistentEntity entity) { + + Object result = evaluate(filterExpression, getEvaluationContextForProperty(entity)); + + if (result instanceof org.bson.Document) { + return PartialIndexFilter.of((org.bson.Document) result); + } + + return PartialIndexFilter.of(BsonUtils.parse(filterExpression, null)); + } + + /** * Creates {@link HashedIndex} wrapped in {@link IndexDefinitionHolder} out of {@link HashIndexed} for a given * {@link MongoPersistentProperty}. 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 7630cb70d..fbddbdbb3 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 @@ -271,6 +271,16 @@ public class MongoPersistentEntityIndexResolverUnitTests { assertThat(indexDefinitions.get(0).getIndexOptions()).containsEntry("name", "my1st"); } + @Test // DATAMONGO-1569 + public void resolvesPartialFilter() { + + List indexDefinitions = prepareMappingContextAndResolveIndexForType( + WithPartialFilter.class); + + assertThat(indexDefinitions.get(0).getIndexOptions()).containsEntry("partialFilterExpression", + org.bson.Document.parse("{'value': {'$exists': true}}")); + } + @Document("Zero") static class IndexOnLevelZero { @Indexed String indexedProperty; @@ -395,6 +405,11 @@ public class MongoPersistentEntityIndexResolverUnitTests { static class WithIndexNameAsExpression { @Indexed(name = "#{'my' + 1 + 'st'}") String spelIndexName; } + + @Document + class WithPartialFilter { + @Indexed(partialFilter = "{'value': {'$exists': true}}") String withPartialFilter; + } } @Target({ ElementType.FIELD })