From 332e63ab8c66834b45fe3103ae21ec0c12edd0bf Mon Sep 17 00:00:00 2001
From: Julia <5765049+sxhinzvc@users.noreply.github.com>
Date: Wed, 11 Oct 2023 16:04:51 -0400
Subject: [PATCH] Add support for Compound Wildcard Indexes.
See #4471
---
.../CompoundWildcardIndexDefinition.java | 60 +++++++
.../core/index/CompoundWildcardIndexed.java | 131 +++++++++++++++
.../MongoPersistentEntityIndexResolver.java | 61 ++++++-
...ersistentEntityIndexResolverUnitTests.java | 154 +++++++++++++++++-
4 files changed, 400 insertions(+), 6 deletions(-)
create mode 100644 spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/CompoundWildcardIndexDefinition.java
create mode 100644 spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/CompoundWildcardIndexed.java
diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/CompoundWildcardIndexDefinition.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/CompoundWildcardIndexDefinition.java
new file mode 100644
index 000000000..8dc99cd84
--- /dev/null
+++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/CompoundWildcardIndexDefinition.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2014-2023 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
+ *
+ * https://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 org.bson.Document;
+import org.springframework.util.Assert;
+
+/**
+ * {@link CompoundWildcardIndexDefinition} is a specific {@link Index} that includes one {@link WildcardIndex} and
+ * one or more non-wildcard fields.
+ *
+ * @author Julia Lee
+ * @since 4.2
+ */
+public class CompoundWildcardIndexDefinition extends WildcardIndex {
+
+ private final Document indexKeys;
+
+ /**
+ * Creates a new {@link CompoundWildcardIndexDefinition} for the given {@literal wildcardPath} and {@literal keys}.
+ * If {@literal wildcardPath} is empty, the wildcard index will apply to the root entity, using {@code $**}.
+ *
+ *
+ * @param wildcardPath can be a {@literal empty} {@link String}.
+ */
+ public CompoundWildcardIndexDefinition(String wildcardPath, Document indexKeys) {
+
+ super(wildcardPath);
+ this.indexKeys = indexKeys;
+ }
+
+ @Override
+ public Document getIndexKeys() {
+
+ Document document = new Document();
+ document.putAll(indexKeys);
+ document.putAll(super.getIndexKeys());
+ return document;
+ }
+
+ @Override
+ public Document getIndexOptions() {
+
+ Document options = super.getIndexOptions();
+ return options;
+ }
+}
diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/CompoundWildcardIndexed.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/CompoundWildcardIndexed.java
new file mode 100644
index 000000000..78b06f2ac
--- /dev/null
+++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/CompoundWildcardIndexed.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright 2011-2023 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
+ *
+ * https://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 org.springframework.core.annotation.AliasFor;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Mark a class to use compound wildcard indexes.
+ *
+ *
+ * @Document
+ * @CompoundWildcardIndexed(wildcardFieldName = "address", fields = "{'firstname': 1}")
+ * class Person {
+ * String firstname;
+ * Address address;
+ * }
+ *
+ * db.product.createIndex({"address.$**": 1, "firstname": 1})
+ *
+ *
+ * {@literal wildcardProjection} can be used to specify keys to in-/exclude in the index.
+ *
+ *
+ *
+ * @Document
+ * @CompoundWildcardIndexed(wildcardProjection = "{'address.zip': 0}", fields = "{'firstname': 1}")
+ * class Person {
+ * String firstname;
+ * Address address;
+ * }
+ *
+ * db.user.createIndex({"$**": 1, "firstname": 1}, {"wildcardProjection": {"address.zip": 0}})
+ *
+ *
+ * @author Julia Lee
+ */
+@Target({ ElementType.TYPE })
+@Documented
+@WildcardIndexed
+@CompoundIndex
+@Retention(RetentionPolicy.RUNTIME)
+public @interface CompoundWildcardIndexed {
+
+ /**
+ * The name of the sub-field to which a wildcard index is applied. If empty, the wildcard term will resolve to "$**".
+ *
+ * @return empty by default.
+ */
+ String wildcardFieldName() default "";
+
+ /**
+ * Explicitly specify sub-fields to be in-/excluded as a {@link org.bson.Document#parse(String) parsable} String.
+ *
+ * NOTE: Can only be applied on when wildcard term is "$**"
+ *
+ * @return empty by default.
+ */
+ @AliasFor(annotation = WildcardIndexed.class, attribute = "wildcardProjection")
+ String wildcardProjection() default "";
+
+ /**
+ * Definition of non-wildcard index(es) in JSON format, wherein the keys are the fields to be indexed and the values
+ * define the index direction (1 for ascending, -1 for descending).
+ *
+ *
+ * @Document
+ * @CompoundWildcardIndexed(wildcardProjection = "{ 'address.zip' : 0 }", fields = "{'firstname': 1}")
+ * class Person {
+ * String firstname;
+ * Address address;
+ * }
+ *
+ *
+ * @return empty String by default.
+ */
+ @AliasFor(annotation = CompoundIndex.class, attribute = "def")
+ String fields();
+
+ /**
+ * Index name either as plain value or as {@link org.springframework.expression.spel.standard.SpelExpression template
+ * expression}.
+ *
+ * @return empty by default.
+ */
+ @AliasFor(annotation = WildcardIndexed.class, attribute = "name")
+ 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 {@literal false} by default
+ */
+ @AliasFor(annotation = WildcardIndexed.class, attribute = "useGeneratedName")
+ boolean useGeneratedName() default false;
+
+ /**
+ * Only index the documents in a collection that meet a specified {@link IndexFilter filter expression}.
+ *
+ * @return empty by default.
+ */
+ @AliasFor(annotation = WildcardIndexed.class, attribute = "partialFilter")
+ String partialFilter() default "";
+
+ /**
+ * Defines the collation to apply.
+ *
+ * @return an empty {@link String} by default.
+ */
+ @AliasFor(annotation = WildcardIndexed.class, attribute = "collation")
+ String collation() 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 86c896e7f..9e36d2a60 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
@@ -79,6 +79,7 @@ import org.springframework.util.StringUtils;
* @author Mark Paluch
* @author Dave Perryman
* @author Stefan Tirea
+ * @author Julia Lee
* @since 1.5
*/
public class MongoPersistentEntityIndexResolver implements IndexResolver {
@@ -129,6 +130,7 @@ public class MongoPersistentEntityIndexResolver implements IndexResolver {
indexInformation.addAll(potentiallyCreateCompoundIndexDefinitions("", collection, root));
indexInformation.addAll(potentiallyCreateWildcardIndexDefinitions("", collection, root));
indexInformation.addAll(potentiallyCreateTextIndexDefinition(root, collection));
+ indexInformation.addAll(potentiallyCreateCompoundWildcardDefinition(root, collection));
root.doWithProperties((PropertyHandler) property -> this
.potentiallyAddIndexForProperty(root, property, indexInformation, new CycleGuard()));
@@ -154,6 +156,22 @@ public class MongoPersistentEntityIndexResolver implements IndexResolver {
}
}
});
+
+ if (entity.isAnnotationPresent(CompoundWildcardIndexed.class)) {
+ CompoundWildcardIndexed indexed = entity.getRequiredAnnotation(CompoundWildcardIndexed.class);
+
+ if (!ObjectUtils.isEmpty(indexed.wildcardFieldName()) && !ObjectUtils.isEmpty(indexed.wildcardProjection())) {
+
+ throw new MappingException(
+ String.format("CompoundWildcardIndex.wildcardProjection is only allowed on \"$**\"; Offending property: %s",
+ indexed.wildcardFieldName()));
+ }
+
+ if (ObjectUtils.isEmpty(indexed.wildcardFieldName()) && ObjectUtils.isEmpty(indexed.wildcardProjection())) {
+
+ throw new MappingException(String.format("CompoundWildcardIndex.wildcardProjection is required on \"$**\""));
+ }
+ }
}
private void potentiallyAddIndexForProperty(MongoPersistentEntity> root, MongoPersistentProperty persistentProperty,
@@ -280,7 +298,8 @@ public class MongoPersistentEntityIndexResolver implements IndexResolver {
private List potentiallyCreateCompoundIndexDefinitions(String dotPath, String collection,
MongoPersistentEntity> entity) {
- if (entity.findAnnotation(CompoundIndexes.class) == null && entity.findAnnotation(CompoundIndex.class) == null) {
+ if ((!entity.isAnnotationPresent(CompoundIndexes.class) && !entity.isAnnotationPresent(CompoundIndex.class))
+ || entity.isAnnotationPresent(CompoundWildcardIndexed.class)) {
return Collections.emptyList();
}
@@ -290,7 +309,8 @@ public class MongoPersistentEntityIndexResolver implements IndexResolver {
private List potentiallyCreateWildcardIndexDefinitions(String dotPath, String collection,
MongoPersistentEntity> entity) {
- if (!entity.isAnnotationPresent(WildcardIndexed.class)) {
+ if (!entity.isAnnotationPresent(WildcardIndexed.class)
+ || entity.isAnnotationPresent(CompoundWildcardIndexed.class)) {
return Collections.emptyList();
}
@@ -345,6 +365,19 @@ public class MongoPersistentEntityIndexResolver implements IndexResolver {
}
+ private Collection extends IndexDefinitionHolder> potentiallyCreateCompoundWildcardDefinition(
+ MongoPersistentEntity> entity, String collection) {
+
+ if (!entity.isAnnotationPresent(CompoundWildcardIndexed.class)) {
+ return Collections.emptyList();
+ }
+
+ CompoundWildcardIndexed compoundWildcardIndex = entity.getRequiredAnnotation(CompoundWildcardIndexed.class);
+ IndexDefinitionHolder compoundWildcardIndexDefinition = createCompoundWildcardIndexDefinition(collection,
+ compoundWildcardIndex, entity);
+ return Collections.singletonList(compoundWildcardIndexDefinition);
+ }
+
private void appendTextIndexInformation(DotPath dotPath, Path path, TextIndexDefinitionBuilder indexDefinitionBuilder,
MongoPersistentEntity> entity, TextIndexIncludeOptions includeOptions, CycleGuard guard) {
@@ -483,6 +516,30 @@ public class MongoPersistentEntityIndexResolver implements IndexResolver {
return new IndexDefinitionHolder(dotPath, indexDefinition, collection);
}
+ protected IndexDefinitionHolder createCompoundWildcardIndexDefinition(String collection, CompoundWildcardIndexed index,
+ @Nullable MongoPersistentEntity> entity) {
+
+ String wildcardField = index.wildcardFieldName();
+ org.bson.Document indexKeys = resolveCompoundIndexKeyFromStringDefinition("", index.fields(), entity);
+
+ CompoundWildcardIndexDefinition indexDefinition = new CompoundWildcardIndexDefinition(wildcardField, indexKeys);
+
+ if (StringUtils.hasText(index.wildcardProjection()) && ObjectUtils.isEmpty(wildcardField)) {
+ indexDefinition.wildcardProjection(evaluateWildcardProjection(index.wildcardProjection(), entity));
+ }
+
+ if (StringUtils.hasText(index.partialFilter())) {
+ indexDefinition.partial(evaluatePartialFilter(index.partialFilter(), entity));
+ }
+
+ if (!index.useGeneratedName()) {
+ indexDefinition.named(pathAwareIndexName(index.name(), "", entity, null));
+ }
+
+ indexDefinition.collation(resolveCollation(index, entity));
+ return new IndexDefinitionHolder("", indexDefinition, collection);
+ }
+
private org.bson.Document resolveCompoundIndexKeyFromStringDefinition(String dotPath, String keyDefinitionString,
PersistentEntity, ?> entity) {
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 0cfb8bd09..37ed48282 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
@@ -40,6 +40,7 @@ import org.springframework.data.mapping.MappingException;
import org.springframework.data.mongodb.core.DocumentTestUtils;
import org.springframework.data.mongodb.core.index.MongoPersistentEntityIndexResolver.IndexDefinitionHolder;
import org.springframework.data.mongodb.core.index.MongoPersistentEntityIndexResolverUnitTests.CompoundIndexResolutionTests;
+import org.springframework.data.mongodb.core.index.MongoPersistentEntityIndexResolverUnitTests.CompoundWildcardIndexResolutionTests;
import org.springframework.data.mongodb.core.index.MongoPersistentEntityIndexResolverUnitTests.GeoSpatialIndexResolutionTests;
import org.springframework.data.mongodb.core.index.MongoPersistentEntityIndexResolverUnitTests.IndexResolutionTests;
import org.springframework.data.mongodb.core.index.MongoPersistentEntityIndexResolverUnitTests.MixedIndexResolutionTests;
@@ -62,10 +63,11 @@ import org.springframework.data.util.ClassTypeInformation;
* @author Mark Paluch
* @author Dave Perryman
* @author Stefan Tirea
+ * @author Julia Lee
*/
@RunWith(Suite.class)
@SuiteClasses({ IndexResolutionTests.class, GeoSpatialIndexResolutionTests.class, CompoundIndexResolutionTests.class,
- TextIndexedResolutionTests.class, MixedIndexResolutionTests.class })
+ CompoundWildcardIndexResolutionTests.class, TextIndexedResolutionTests.class, MixedIndexResolutionTests.class })
@SuppressWarnings("unused")
public class MongoPersistentEntityIndexResolverUnitTests {
@@ -601,7 +603,7 @@ public class MongoPersistentEntityIndexResolverUnitTests {
public void compoundIndexDoesNotSpecifyNameWhenUsingGenerateName() {
List indexDefinitions = prepareMappingContextAndResolveIndexForType(
- ComountIndexWithAutogeneratedName.class);
+ CompoundIndexWithAutogeneratedName.class);
IndexDefinition indexDefinition = indexDefinitions.get(0).getIndexDefinition();
assertThat(indexDefinition.getIndexOptions())
@@ -766,10 +768,10 @@ public class MongoPersistentEntityIndexResolverUnitTests {
class IndexDefinedOnSuperClass extends CompoundIndexOnLevelZero {}
- @Document("ComountIndexWithAutogeneratedName")
+ @Document("CompoundIndexWithAutogeneratedName")
@CompoundIndexes({ @CompoundIndex(useGeneratedName = true, def = "{'foo': 1, 'bar': -1}", background = true,
sparse = true, unique = true) })
- class ComountIndexWithAutogeneratedName {}
+ class CompoundIndexWithAutogeneratedName {}
@Document("WithComposedAnnotation")
@ComposedCompoundIndex
@@ -829,6 +831,150 @@ public class MongoPersistentEntityIndexResolverUnitTests {
class WithEvaluatedCollationFromCompoundIndex {}
}
+ /**
+ * Test resolution of {@link CompoundWildcardIndexed}.
+ *
+ * @author Julia Lee
+ */
+ public static class CompoundWildcardIndexResolutionTests {
+
+ @Test // GH-4471
+ public void compoundWildcardIndexOnSingleField() {
+
+ List indexDefinitions = prepareMappingContextAndResolveIndexForType(
+ CompoundWildcardIndexOnFields.class);
+
+ assertThat(indexDefinitions).hasSize(1);
+ assertIndexPathAndCollection(new String[] { "foo.$**", "bar", "baz" }, "CompoundWildcardIndexOnSingleField",
+ indexDefinitions.get(0));
+ }
+
+ @Test // GH-4471
+ public void compoundWildcardIndexOnEntityWithProjection() {
+
+ List indexDefinitions = prepareMappingContextAndResolveIndexForType(
+ CompoundWildcardIndexOnEntity.class);
+
+ assertThat(indexDefinitions).hasSize(1);
+ assertThat(indexDefinitions.get(0)).satisfies(it -> {
+ assertThat(it.getIndexKeys()).isEqualTo(new org.bson.Document().append("$**", 1).append("bar", -1));
+ assertThat(it.getIndexOptions()).containsEntry("wildcardProjection",
+ org.bson.Document.parse("{'foo.something' : 0}"));
+ });
+ }
+
+ @Test // GH-4471
+ public void compoundWildcardIndexWithOptions() {
+
+ List indexDefinitions = prepareMappingContextAndResolveIndexForType(
+ CompoundWildcardIndexWithOptions.class);
+
+ assertThat(indexDefinitions).hasSize(1);
+ assertThat(indexDefinitions.get(0)).satisfies(it -> {
+ assertThat(it.getIndexKeys()).isEqualTo(new org.bson.Document().append("$**", 1).append("foo", 1));
+
+ org.bson.Document indexOptions = it.getIndexOptions();
+ assertThat(indexOptions).containsEntry("name", "my_index_name");
+ assertThat(indexOptions).containsEntry("wildcardProjection", org.bson.Document.parse("{'bar.something' : 1}"));
+ assertThat(indexOptions).containsEntry("collation",
+ new org.bson.Document().append("locale", "en_US").append("strength", 2));
+ assertThat(indexOptions).containsEntry("partialFilterExpression",
+ org.bson.Document.parse("{'value': {'$exists': true}}"));
+ });
+ }
+
+ @Test // GH-4471
+ public void compoundWildcardIndexWithCollationFromDocumentAnnotation() {
+
+ List indexDefinitions = prepareMappingContextAndResolveIndexForType(
+ CompoundWildcardIndexWithCollationOnDocument.class);
+
+ assertThat(indexDefinitions.get(0)).satisfies(it -> {
+ assertThat(it.getIndexKeys()).isEqualTo(new org.bson.Document().append("foo.$**", 1).append("bar", 1));
+ assertThat(it.getIndexOptions()).containsEntry("collation",
+ new org.bson.Document().append("locale", "en_US").append("strength", 2));
+ });
+ }
+
+ @Test // GH-4471
+ public void compoundWildcardIndexWithEvaluatedCollationFromAnnotation() {
+
+ List indexDefinitions = prepareMappingContextAndResolveIndexForType(
+ CompoundWildcardIndexWithEvaluatedCollation.class);
+
+ assertThat(indexDefinitions.get(0)).satisfies(it -> {
+ assertThat(it.getIndexKeys()).isEqualTo(new org.bson.Document().append("foo.$**", 1).append("bar", 1));
+ assertThat(it.getIndexOptions()).containsEntry("collation", new org.bson.Document().append("locale", "de_AT"));
+ });
+ }
+
+ @Test // GH-4471
+ public void rejectsWildcardProjectionOnSingleField() {
+
+ assertThatExceptionOfType(MappingException.class).isThrownBy(() ->
+ prepareMappingContextAndResolveIndexForType(IncorrectCompoundWildcardIndexOnFieldWithProjection.class));
+ }
+
+ @Test // GH-4471
+ public void requiresWildcardProjectionOnEntireEntity() {
+
+ assertThatExceptionOfType(MappingException.class).isThrownBy(() ->
+ prepareMappingContextAndResolveIndexForType(IncorrectCompoundWildcardIndexOnEntityWithoutProjection.class));
+ }
+
+ @Test // GH-4471
+ public void resolvesMultipleIndexesWithCompoundWildcardIndex() {
+
+ List indexDefinitions = prepareMappingContextAndResolveIndexForType(
+ MultipleIndexes.class);
+
+ assertThat(indexDefinitions).hasSize(2);
+
+ assertThat(indexDefinitions.get(0).getIndexDefinition()).isInstanceOf(CompoundWildcardIndexDefinition.class);
+ assertThat(indexDefinitions.get(1).getIndexDefinition()).isInstanceOf(Index.class);
+
+ assertThat(indexDefinitions.get(0).getIndexKeys()).isEqualTo(new org.bson.Document().append("foo.$**", 1)
+ .append("bar", 1));
+ assertThat(indexDefinitions.get(1).getIndexKeys()).isEqualTo(new org.bson.Document().append("one", 1));
+ }
+
+ @Document("CompoundWildcardIndexOnSingleField")
+ @CompoundWildcardIndexed(wildcardFieldName = "foo", fields = "{'bar': 1, 'baz': 1}")
+ class CompoundWildcardIndexOnFields {}
+
+ @Document
+ @CompoundWildcardIndexed(wildcardFieldName = "foo", wildcardProjection = "{}", fields = "{'bar': 1}")
+ class IncorrectCompoundWildcardIndexOnFieldWithProjection {}
+
+ @Document
+ @CompoundWildcardIndexed(fields = "{ 'bar': 1 }")
+ class IncorrectCompoundWildcardIndexOnEntityWithoutProjection {}
+
+ @Document
+ @CompoundWildcardIndexed(wildcardProjection = "{'foo.something' : 0}", fields = "{'bar': -1}")
+ class CompoundWildcardIndexOnEntity {}
+
+ @Document
+ @CompoundWildcardIndexed(fields = "{'foo': 1}", wildcardProjection = "{'bar.something': 1}", name = "my_index_name",
+ collation = "{'locale': 'en_US', 'strength': 2}", partialFilter = "{'value': {'$exists': true}}")
+ class CompoundWildcardIndexWithOptions {}
+
+ @Document(collation = "{'locale': 'en_US', 'strength': 2}")
+ @CompoundWildcardIndexed(wildcardFieldName = "foo", fields = "{'bar': 1}")
+ class CompoundWildcardIndexWithCollationOnDocument {}
+
+ @Document(collation = "{'locale': 'en_US', 'strength': 2}")
+ @CompoundWildcardIndexed(wildcardFieldName = "foo", fields = "{'bar': 1}", collation = "#{{'locale' : 'de' + '_' + 'AT'}}")
+ class CompoundWildcardIndexWithEvaluatedCollation {}
+
+ @Document
+ @CompoundWildcardIndexed(wildcardFieldName = "foo", fields = "{'bar': 1}")
+ class MultipleIndexes {
+ @Indexed String one;
+ }
+
+ }
+
public static class TextIndexedResolutionTests {
@Test // DATAMONGO-937