Skip to content

Add collation for an index via @CompoundIndex and @Index annotations. #4131

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
* @author Johno Crawford
* @author Christoph Strobl
* @author Dave Perryman
* @author Stefan Tirea
*/
@Target({ ElementType.TYPE })
@Documented
Expand Down Expand Up @@ -163,4 +164,19 @@
* @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 "";
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
* @author Christoph Strobl
* @author Jordi Llach
* @author Mark Paluch
* @author Stefan Tirea
*/
@Target({ ElementType.ANNOTATION_TYPE, ElementType.FIELD })
@Retention(RetentionPolicy.RUNTIME)
Expand Down Expand Up @@ -173,4 +174,14 @@
* @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 "";
}
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@
* @author Martin Macko
* @author Mark Paluch
* @author Dave Perryman
* @author Stefan Tirea
* @since 1.5
*/
public class MongoPersistentEntityIndexResolver implements IndexResolver {
Expand Down Expand Up @@ -453,6 +454,10 @@ protected IndexDefinitionHolder createCompoundIndexDefinition(String dotPath, St
indexDefinition.partial(evaluatePartialFilter(index.partialFilter(), entity));
}

if (StringUtils.hasText(index.collation())) {
indexDefinition.collation(Collation.parse(index.collation()));
}

return new IndexDefinitionHolder(dotPath, indexDefinition, collection);
}

Expand Down Expand Up @@ -572,6 +577,10 @@ protected IndexDefinitionHolder createIndexDefinition(String dotPath, String col
indexDefinition.partial(evaluatePartialFilter(index.partialFilter(), persistentProperty.getOwner()));
}

if (StringUtils.hasText(index.collation())) {
indexDefinition.collation(Collation.parse(index.collation()));
}

return new IndexDefinitionHolder(dotPath, indexDefinition, collection);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
*
* @author Oliver Gierke
* @author Christoph Strobl
* @author Stefan Tirea
*/
public class IndexInfoUnitTests {

Expand All @@ -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() {
Expand Down Expand Up @@ -87,7 +89,14 @@ public void identifiesWildcardIndexCorrectly() {

@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) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@
* @author Christoph Strobl
* @author Mark Paluch
* @author Dave Perryman
* @author Stefan Tirea
*/
@RunWith(Suite.class)
@SuiteClasses({ IndexResolutionTests.class, GeoSpatialIndexResolutionTests.class, CompoundIndexResolutionTests.class,
Expand Down Expand Up @@ -699,6 +700,19 @@ public void singleIndexWithPartialFilter() {
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 {

Expand Down Expand Up @@ -774,6 +788,11 @@ class RepeatedCompoundIndex {}
@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 {
Expand Down Expand Up @@ -1400,6 +1419,18 @@ public void shouldSkipMapStructuresUnlessAnnotatedWithWildcardIndex() {
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 {

Expand Down Expand Up @@ -1717,6 +1748,12 @@ class WithComposedHashedIndexAndIndex {
@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)
Expand Down