Skip to content

Commit 068bfc6

Browse files
StefanTireachristophstrobl
authored andcommitted
Add collation for an index via @CompoundIndex and @Index annotations.
Closes #3002, closes #4130
1 parent 74460e6 commit 068bfc6

File tree

5 files changed

+83
-1
lines changed

5 files changed

+83
-1
lines changed

spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/CompoundIndex.java

+16
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
* @author Johno Crawford
4747
* @author Christoph Strobl
4848
* @author Dave Perryman
49+
* @author Stefan Tirea
4950
*/
5051
@Target({ ElementType.TYPE })
5152
@Documented
@@ -163,4 +164,19 @@
163164
* @since 3.1
164165
*/
165166
String partialFilter() default "";
167+
168+
/**
169+
* The actual collation definition in JSON format or a {@link org.springframework.expression.spel.standard.SpelExpression
170+
* template expression} resolving to either a JSON String or a {@link org.bson.Document}. The keys of the JSON
171+
* document are configuration options for the collation (language-specific rules for string comparison).
172+
* <br><br>
173+
* TODO write code documentation & example!!!
174+
* <br>
175+
*
176+
* @return empty String by default.
177+
* @see <a href=
178+
* "https://www.mongodb.com/docs/manual/reference/collation/">https://www.mongodb.com/docs/manual/reference/collation/</a>
179+
* @since 3.4
180+
*/
181+
String collation() default "";
166182
}

spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/Indexed.java

+11
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
* @author Christoph Strobl
3232
* @author Jordi Llach
3333
* @author Mark Paluch
34+
* @author Stefan Tirea
3435
*/
3536
@Target({ ElementType.ANNOTATION_TYPE, ElementType.FIELD })
3637
@Retention(RetentionPolicy.RUNTIME)
@@ -173,4 +174,14 @@
173174
* @since 3.1
174175
*/
175176
String partialFilter() default "";
177+
178+
/**
179+
* Apply collation configuration for field <br />
180+
*
181+
* @return empty by default.
182+
* @see <a href=
183+
* "https://www.mongodb.com/docs/manual/reference/collation/">https://www.mongodb.com/docs/manual/reference/collation//</a>
184+
* @since 3.1
185+
*/
186+
String collation() default "";
176187
}

spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexResolver.java

+9
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@
7474
* @author Martin Macko
7575
* @author Mark Paluch
7676
* @author Dave Perryman
77+
* @author Stefan Tirea
7778
* @since 1.5
7879
*/
7980
public class MongoPersistentEntityIndexResolver implements IndexResolver {
@@ -453,6 +454,10 @@ protected IndexDefinitionHolder createCompoundIndexDefinition(String dotPath, St
453454
indexDefinition.partial(evaluatePartialFilter(index.partialFilter(), entity));
454455
}
455456

457+
if (StringUtils.hasText(index.collation())) {
458+
indexDefinition.collation(Collation.parse(index.collation()));
459+
}
460+
456461
return new IndexDefinitionHolder(dotPath, indexDefinition, collection);
457462
}
458463

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

580+
if (StringUtils.hasText(index.collation())) {
581+
indexDefinition.collation(Collation.parse(index.collation()));
582+
}
583+
575584
return new IndexDefinitionHolder(dotPath, indexDefinition, collection);
576585
}
577586

spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/IndexInfoUnitTests.java

+10-1
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
*
3030
* @author Oliver Gierke
3131
* @author Christoph Strobl
32+
* @author Stefan Tirea
3233
*/
3334
public class IndexInfoUnitTests {
3435

@@ -37,6 +38,7 @@ public class IndexInfoUnitTests {
3738
static final String INDEX_WITH_EXPIRATION_TIME = "{ \"v\" : 2, \"key\" : { \"lastModifiedDate\" : 1 },\"name\" : \"expire-after-last-modified\", \"ns\" : \"db.collectio\", \"expireAfterSeconds\" : 3600 }";
3839
static final String HASHED_INDEX = "{ \"v\" : 2, \"key\" : { \"score\" : \"hashed\" }, \"name\" : \"score_hashed\", \"ns\" : \"db.collection\" }";
3940
static final String WILDCARD_INDEX = "{ \"v\" : 2, \"key\" : { \"$**\" : 1 }, \"name\" : \"$**_1\", \"wildcardProjection\" : { \"fieldA\" : 0, \"fieldB.fieldC\" : 0 } }";
41+
static final String INDEX_WITH_COLLATION = "{ \"v\" : 2, \"key\" : { \"_id\" : 1 }, \"name\" : \"projectName\", \"collation\": { \"locale\": \"en_US\", \"strength\": 2 } }";
4042

4143
@Test
4244
public void isIndexForFieldsCorrectly() {
@@ -87,7 +89,14 @@ public void identifiesWildcardIndexCorrectly() {
8789

8890
@Test // GH-3225
8991
public void readsWildcardIndexProjectionCorrectly() {
90-
assertThat(getIndexInfo(WILDCARD_INDEX).getWildcardProjection()).contains(new Document("fieldA", 0).append("fieldB.fieldC", 0));
92+
assertThat(getIndexInfo(WILDCARD_INDEX).getWildcardProjection())
93+
.contains(new Document("fieldA", 0).append("fieldB.fieldC", 0));
94+
}
95+
96+
@Test // DATAMONGO-2133
97+
public void collationParsedCorrectly() {
98+
assertThat(getIndexInfo(INDEX_WITH_COLLATION).getCollation())
99+
.contains(Document.parse("{ \"locale\": \"en_US\", \"strength\": 2 }"));
91100
}
92101

93102
private static IndexInfo getIndexInfo(String documentJson) {

spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexResolverUnitTests.java

+37
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@
6161
* @author Christoph Strobl
6262
* @author Mark Paluch
6363
* @author Dave Perryman
64+
* @author Stefan Tirea
6465
*/
6566
@RunWith(Suite.class)
6667
@SuiteClasses({ IndexResolutionTests.class, GeoSpatialIndexResolutionTests.class, CompoundIndexResolutionTests.class,
@@ -699,6 +700,19 @@ public void singleIndexWithPartialFilter() {
699700
org.bson.Document.parse("{'value': {'$exists': true}}"));
700701
}
701702

703+
@Test // DATAMONGO-2133
704+
public void compoundIndexWithCollation() {
705+
706+
List<IndexDefinitionHolder> indexDefinitions = prepareMappingContextAndResolveIndexForType(
707+
CompoundIndexWithCollation.class);
708+
709+
IndexDefinition indexDefinition = indexDefinitions.get(0).getIndexDefinition();
710+
assertThat(indexDefinition.getIndexOptions())
711+
.isEqualTo(new org.bson.Document().append("name", "compound_index_with_collation").append("collation",
712+
new org.bson.Document().append("locale", "en_US").append("strength", 2)));
713+
assertThat(indexDefinition.getIndexKeys()).isEqualTo(new org.bson.Document().append("foo", 1));
714+
}
715+
702716
@Document("CompoundIndexOnLevelOne")
703717
class CompoundIndexOnLevelOne {
704718

@@ -774,6 +788,11 @@ class RepeatedCompoundIndex {}
774788
@CompoundIndex(name = "compound_index_with_partial", def = "{'foo': 1, 'bar': -1}", background = true,
775789
unique = true, partialFilter = "{'value': {'$exists': true}}")
776790
class SingleCompoundIndexWithPartialFilter {}
791+
792+
@Document
793+
@CompoundIndex(name = "compound_index_with_collation", def = "{'foo': 1}",
794+
collation = "{'locale': 'en_US', 'strength': 2}")
795+
class CompoundIndexWithCollation {}
777796
}
778797

779798
public static class TextIndexedResolutionTests {
@@ -1400,6 +1419,18 @@ public void shouldSkipMapStructuresUnlessAnnotatedWithWildcardIndex() {
14001419
assertThat(indexDefinitions).hasSize(1);
14011420
}
14021421

1422+
@Test // DATAMONGO-2133
1423+
public void indexedWithCollation() {
1424+
1425+
List<IndexDefinitionHolder> indexDefinitions = prepareMappingContextAndResolveIndexForType(
1426+
IndexedWithCollation.class);
1427+
1428+
IndexDefinition indexDefinition = indexDefinitions.get(0).getIndexDefinition();
1429+
assertThat(indexDefinition.getIndexOptions()).isEqualTo(new org.bson.Document().append("name", "value")
1430+
.append("unique", true)
1431+
.append("collation", new org.bson.Document().append("locale", "en_US").append("strength", 2)));
1432+
}
1433+
14031434
@Document
14041435
class MixedIndexRoot {
14051436

@@ -1717,6 +1748,12 @@ class WithComposedHashedIndexAndIndex {
17171748
@ComposedHashIndexed(name = "idx-name") String value;
17181749
}
17191750

1751+
@Document
1752+
class IndexedWithCollation {
1753+
@Indexed(collation = "{'locale': 'en_US', 'strength': 2}", unique = true) //
1754+
private String value;
1755+
}
1756+
17201757
@HashIndexed
17211758
@Indexed
17221759
@Retention(RetentionPolicy.RUNTIME)

0 commit comments

Comments
 (0)