Add collation for an index via @CompoundIndex and @Index annotations.
Closes #3002, closes #4130 Original Pull Request: #4131
This commit is contained in:
committed by
Christoph Strobl
parent
2a4ee12363
commit
ff9d338bd7
@@ -46,6 +46,7 @@ import java.lang.annotation.Target;
|
||||
* @author Johno Crawford
|
||||
* @author Christoph Strobl
|
||||
* @author Dave Perryman
|
||||
* @author Stefan Tirea
|
||||
*/
|
||||
@Target({ ElementType.TYPE })
|
||||
@Documented
|
||||
@@ -163,4 +164,19 @@ public @interface CompoundIndex {
|
||||
* @since 3.1
|
||||
*/
|
||||
String partialFilter() default "";
|
||||
|
||||
/**
|
||||
* The actual collation definition in JSON format or a {@link org.springframework.expression.spel.standard.SpelExpression
|
||||
* template expression} resolving to either a JSON String or a {@link org.bson.Document}. The keys of the JSON
|
||||
* document are configuration options for the collation (language-specific rules for string comparison).
|
||||
* <br><br>
|
||||
* TODO write code documentation & example!!!
|
||||
* <br>
|
||||
*
|
||||
* @return empty String by default.
|
||||
* @see <a href=
|
||||
* "https://www.mongodb.com/docs/manual/reference/collation/">https://www.mongodb.com/docs/manual/reference/collation/</a>
|
||||
* @since 3.4
|
||||
*/
|
||||
String collation() default "";
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@ import java.lang.annotation.Target;
|
||||
* @author Christoph Strobl
|
||||
* @author Jordi Llach
|
||||
* @author Mark Paluch
|
||||
* @author Stefan Tirea
|
||||
*/
|
||||
@Target({ ElementType.ANNOTATION_TYPE, ElementType.FIELD })
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@@ -173,4 +174,14 @@ public @interface Indexed {
|
||||
* @since 3.1
|
||||
*/
|
||||
String partialFilter() default "";
|
||||
|
||||
/**
|
||||
* Apply collation configuration for field <br />
|
||||
*
|
||||
* @return empty by default.
|
||||
* @see <a href=
|
||||
* "https://www.mongodb.com/docs/manual/reference/collation/">https://www.mongodb.com/docs/manual/reference/collation//</a>
|
||||
* @since 3.1
|
||||
*/
|
||||
String collation() default "";
|
||||
}
|
||||
|
||||
@@ -74,6 +74,7 @@ import org.springframework.util.StringUtils;
|
||||
* @author Martin Macko
|
||||
* @author Mark Paluch
|
||||
* @author Dave Perryman
|
||||
* @author Stefan Tirea
|
||||
* @since 1.5
|
||||
*/
|
||||
public class MongoPersistentEntityIndexResolver implements IndexResolver {
|
||||
@@ -453,6 +454,10 @@ public class MongoPersistentEntityIndexResolver implements IndexResolver {
|
||||
indexDefinition.partial(evaluatePartialFilter(index.partialFilter(), entity));
|
||||
}
|
||||
|
||||
if (StringUtils.hasText(index.collation())) {
|
||||
indexDefinition.collation(Collation.parse(index.collation()));
|
||||
}
|
||||
|
||||
return new IndexDefinitionHolder(dotPath, indexDefinition, collection);
|
||||
}
|
||||
|
||||
@@ -572,6 +577,10 @@ public class MongoPersistentEntityIndexResolver implements IndexResolver {
|
||||
indexDefinition.partial(evaluatePartialFilter(index.partialFilter(), persistentProperty.getOwner()));
|
||||
}
|
||||
|
||||
if (StringUtils.hasText(index.collation())) {
|
||||
indexDefinition.collation(Collation.parse(index.collation()));
|
||||
}
|
||||
|
||||
return new IndexDefinitionHolder(dotPath, indexDefinition, collection);
|
||||
}
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@ import org.springframework.data.domain.Sort.Direction;
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Christoph Strobl
|
||||
* @author Stefan Tirea
|
||||
*/
|
||||
public class IndexInfoUnitTests {
|
||||
|
||||
@@ -37,6 +38,7 @@ public class IndexInfoUnitTests {
|
||||
static final String INDEX_WITH_EXPIRATION_TIME = "{ \"v\" : 2, \"key\" : { \"lastModifiedDate\" : 1 },\"name\" : \"expire-after-last-modified\", \"ns\" : \"db.collectio\", \"expireAfterSeconds\" : 3600 }";
|
||||
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 } }";
|
||||
|
||||
@Test
|
||||
public void isIndexForFieldsCorrectly() {
|
||||
@@ -87,7 +89,14 @@ public class IndexInfoUnitTests {
|
||||
|
||||
@Test // GH-3225
|
||||
public void readsWildcardIndexProjectionCorrectly() {
|
||||
assertThat(getIndexInfo(WILDCARD_INDEX).getWildcardProjection()).contains(new Document("fieldA", 0).append("fieldB.fieldC", 0));
|
||||
assertThat(getIndexInfo(WILDCARD_INDEX).getWildcardProjection())
|
||||
.contains(new Document("fieldA", 0).append("fieldB.fieldC", 0));
|
||||
}
|
||||
|
||||
@Test // DATAMONGO-2133
|
||||
public void collationParsedCorrectly() {
|
||||
assertThat(getIndexInfo(INDEX_WITH_COLLATION).getCollation())
|
||||
.contains(Document.parse("{ \"locale\": \"en_US\", \"strength\": 2 }"));
|
||||
}
|
||||
|
||||
private static IndexInfo getIndexInfo(String documentJson) {
|
||||
|
||||
@@ -61,6 +61,7 @@ import org.springframework.data.util.ClassTypeInformation;
|
||||
* @author Christoph Strobl
|
||||
* @author Mark Paluch
|
||||
* @author Dave Perryman
|
||||
* @author Stefan Tirea
|
||||
*/
|
||||
@RunWith(Suite.class)
|
||||
@SuiteClasses({ IndexResolutionTests.class, GeoSpatialIndexResolutionTests.class, CompoundIndexResolutionTests.class,
|
||||
@@ -699,6 +700,19 @@ public class MongoPersistentEntityIndexResolverUnitTests {
|
||||
org.bson.Document.parse("{'value': {'$exists': true}}"));
|
||||
}
|
||||
|
||||
@Test // DATAMONGO-2133
|
||||
public void compoundIndexWithCollation() {
|
||||
|
||||
List<IndexDefinitionHolder> indexDefinitions = prepareMappingContextAndResolveIndexForType(
|
||||
CompoundIndexWithCollation.class);
|
||||
|
||||
IndexDefinition indexDefinition = indexDefinitions.get(0).getIndexDefinition();
|
||||
assertThat(indexDefinition.getIndexOptions())
|
||||
.isEqualTo(new org.bson.Document().append("name", "compound_index_with_collation").append("collation",
|
||||
new org.bson.Document().append("locale", "en_US").append("strength", 2)));
|
||||
assertThat(indexDefinition.getIndexKeys()).isEqualTo(new org.bson.Document().append("foo", 1));
|
||||
}
|
||||
|
||||
@Document("CompoundIndexOnLevelOne")
|
||||
class CompoundIndexOnLevelOne {
|
||||
|
||||
@@ -774,6 +788,11 @@ public class MongoPersistentEntityIndexResolverUnitTests {
|
||||
@CompoundIndex(name = "compound_index_with_partial", def = "{'foo': 1, 'bar': -1}", background = true,
|
||||
unique = true, partialFilter = "{'value': {'$exists': true}}")
|
||||
class SingleCompoundIndexWithPartialFilter {}
|
||||
|
||||
@Document
|
||||
@CompoundIndex(name = "compound_index_with_collation", def = "{'foo': 1}",
|
||||
collation = "{'locale': 'en_US', 'strength': 2}")
|
||||
class CompoundIndexWithCollation {}
|
||||
}
|
||||
|
||||
public static class TextIndexedResolutionTests {
|
||||
@@ -1400,6 +1419,18 @@ public class MongoPersistentEntityIndexResolverUnitTests {
|
||||
assertThat(indexDefinitions).hasSize(1);
|
||||
}
|
||||
|
||||
@Test // DATAMONGO-2133
|
||||
public void indexedWithCollation() {
|
||||
|
||||
List<IndexDefinitionHolder> indexDefinitions = prepareMappingContextAndResolveIndexForType(
|
||||
IndexedWithCollation.class);
|
||||
|
||||
IndexDefinition indexDefinition = indexDefinitions.get(0).getIndexDefinition();
|
||||
assertThat(indexDefinition.getIndexOptions()).isEqualTo(new org.bson.Document().append("name", "value")
|
||||
.append("unique", true)
|
||||
.append("collation", new org.bson.Document().append("locale", "en_US").append("strength", 2)));
|
||||
}
|
||||
|
||||
@Document
|
||||
class MixedIndexRoot {
|
||||
|
||||
@@ -1717,6 +1748,12 @@ public class MongoPersistentEntityIndexResolverUnitTests {
|
||||
@ComposedHashIndexed(name = "idx-name") String value;
|
||||
}
|
||||
|
||||
@Document
|
||||
class IndexedWithCollation {
|
||||
@Indexed(collation = "{'locale': 'en_US', 'strength': 2}", unique = true) //
|
||||
private String value;
|
||||
}
|
||||
|
||||
@HashIndexed
|
||||
@Indexed
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
|
||||
Reference in New Issue
Block a user