Skip to content

Commit 4cdd387

Browse files
DATAMONGO-1854 - Allow Collation to be configured on entity level.
The collation can now also be configured on entity level and gets applied via MongoTemplate. However one can alway override a default collation by adding the collation explicitly to either the Query or one of the Options available for various operations. When it comes to the repository level the hierarchy is method parameter over query annotation over entity metadata.
1 parent 173ddaa commit 4cdd387

29 files changed

+1785
-201
lines changed

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

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -120,19 +120,14 @@ public String ensureIndex(final IndexDefinition indexDefinition) {
120120

121121
return execute(collection -> {
122122

123-
Document indexOptions = indexDefinition.getIndexOptions();
123+
MongoPersistentEntity<?> entity = lookupPersistentEntity(type, collectionName);
124124

125-
IndexOptions ops = IndexConverters.indexDefinitionToIndexOptionsConverter().convert(indexDefinition);
125+
IndexOptions indexOptions = IndexConverters.indexDefinitionToIndexOptionsConverter().convert(indexDefinition);
126126

127-
if (indexOptions.containsKey(PARTIAL_FILTER_EXPRESSION_KEY)) {
127+
indexOptions = addPartialFilterIfPresent(indexOptions, indexDefinition.getIndexOptions(), entity);
128+
indexOptions = addDefaultCollationIfRequired(indexOptions, entity);
128129

129-
Assert.isInstanceOf(Document.class, indexOptions.get(PARTIAL_FILTER_EXPRESSION_KEY));
130-
131-
ops.partialFilterExpression(mapper.getMappedObject((Document) indexOptions.get(PARTIAL_FILTER_EXPRESSION_KEY),
132-
lookupPersistentEntity(type, collectionName)));
133-
}
134-
135-
return collection.createIndex(indexDefinition.getIndexKeys(), ops);
130+
return collection.createIndex(indexDefinition.getIndexKeys(), indexOptions);
136131
});
137132
}
138133

@@ -192,7 +187,7 @@ public List<IndexInfo> doInCollection(MongoCollection<Document> collection)
192187

193188
private List<IndexInfo> getIndexData(MongoCursor<Document> cursor) {
194189

195-
List<IndexInfo> indexInfoList = new ArrayList<IndexInfo>();
190+
List<IndexInfo> indexInfoList = new ArrayList<>();
196191

197192
while (cursor.hasNext()) {
198193

@@ -217,4 +212,25 @@ public <T> T execute(CollectionCallback<T> callback) {
217212

218213
return mongoOperations.execute(collectionName, callback);
219214
}
215+
216+
private IndexOptions addPartialFilterIfPresent(IndexOptions ops, Document sourceOptions,
217+
@Nullable MongoPersistentEntity<?> entity) {
218+
219+
if (!sourceOptions.containsKey(PARTIAL_FILTER_EXPRESSION_KEY)) {
220+
return ops;
221+
}
222+
223+
Assert.isInstanceOf(Document.class, sourceOptions.get(PARTIAL_FILTER_EXPRESSION_KEY));
224+
return ops.partialFilterExpression(
225+
mapper.getMappedObject((Document) sourceOptions.get(PARTIAL_FILTER_EXPRESSION_KEY), entity));
226+
}
227+
228+
private static IndexOptions addDefaultCollationIfRequired(IndexOptions ops, MongoPersistentEntity<?> entity) {
229+
230+
if (ops.getCollation() != null || entity == null || !entity.hasCollation()) {
231+
return ops;
232+
}
233+
234+
return ops.collation(entity.getCollation().toMongoCollation());
235+
}
220236
}

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

Lines changed: 34 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -94,23 +94,16 @@ public Mono<String> ensureIndex(final IndexDefinition indexDefinition) {
9494

9595
return mongoOperations.execute(collectionName, collection -> {
9696

97-
Document indexOptions = indexDefinition.getIndexOptions();
97+
MongoPersistentEntity<?> entity = type
98+
.map(val -> (MongoPersistentEntity) queryMapper.getMappingContext().getRequiredPersistentEntity(val))
99+
.orElseGet(() -> lookupPersistentEntity(collectionName));
98100

99-
IndexOptions ops = IndexConverters.indexDefinitionToIndexOptionsConverter().convert(indexDefinition);
101+
IndexOptions indexOptions = IndexConverters.indexDefinitionToIndexOptionsConverter().convert(indexDefinition);
100102

101-
if (indexOptions.containsKey(PARTIAL_FILTER_EXPRESSION_KEY)) {
103+
indexOptions = addPartialFilterIfPresent(indexOptions, indexDefinition.getIndexOptions(), entity);
104+
indexOptions = addDefaultCollationIfRequired(indexOptions, entity);
102105

103-
Assert.isInstanceOf(Document.class, indexOptions.get(PARTIAL_FILTER_EXPRESSION_KEY));
104-
105-
MongoPersistentEntity<?> entity = type
106-
.map(val -> (MongoPersistentEntity) queryMapper.getMappingContext().getRequiredPersistentEntity(val))
107-
.orElseGet(() -> lookupPersistentEntity(collectionName));
108-
109-
ops = ops.partialFilterExpression(
110-
queryMapper.getMappedObject(indexOptions.get(PARTIAL_FILTER_EXPRESSION_KEY, Document.class), entity));
111-
}
112-
113-
return collection.createIndex(indexDefinition.getIndexKeys(), ops);
106+
return collection.createIndex(indexDefinition.getIndexKeys(), indexOptions);
114107

115108
}).next();
116109
}
@@ -126,26 +119,50 @@ private MongoPersistentEntity<?> lookupPersistentEntity(String collection) {
126119
.orElse(null);
127120
}
128121

129-
/* (non-Javadoc)
122+
/*
123+
* (non-Javadoc)
130124
* @see org.springframework.data.mongodb.core.index.ReactiveIndexOperations#dropIndex(java.lang.String)
131125
*/
132126
public Mono<Void> dropIndex(final String name) {
133127
return mongoOperations.execute(collectionName, collection -> collection.dropIndex(name)).then();
134128
}
135129

136-
/* (non-Javadoc)
130+
/*
131+
* (non-Javadoc)
137132
* @see org.springframework.data.mongodb.core.index.ReactiveIndexOperations#dropAllIndexes()
138133
*/
139134
public Mono<Void> dropAllIndexes() {
140135
return dropIndex("*");
141136
}
142137

143-
/* (non-Javadoc)
138+
/*
139+
* (non-Javadoc)
144140
* @see org.springframework.data.mongodb.core.index.ReactiveIndexOperations#getIndexInfo()
145141
*/
146142
public Flux<IndexInfo> getIndexInfo() {
147143

148144
return mongoOperations.execute(collectionName, collection -> collection.listIndexes(Document.class)) //
149145
.map(IndexConverters.documentToIndexInfoConverter()::convert);
150146
}
147+
148+
private IndexOptions addPartialFilterIfPresent(IndexOptions ops, Document sourceOptions,
149+
@Nullable MongoPersistentEntity<?> entity) {
150+
151+
if (!sourceOptions.containsKey(PARTIAL_FILTER_EXPRESSION_KEY)) {
152+
return ops;
153+
}
154+
155+
Assert.isInstanceOf(Document.class, sourceOptions.get(PARTIAL_FILTER_EXPRESSION_KEY));
156+
return ops.partialFilterExpression(
157+
queryMapper.getMappedObject((Document) sourceOptions.get(PARTIAL_FILTER_EXPRESSION_KEY), entity));
158+
}
159+
160+
private static IndexOptions addDefaultCollationIfRequired(IndexOptions ops, MongoPersistentEntity<?> entity) {
161+
162+
if (ops.getCollation() != null || entity == null || !entity.hasCollation()) {
163+
return ops;
164+
}
165+
166+
return ops.collation(entity.getCollation().toMongoCollation());
167+
}
151168
}

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

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,31 @@ public class FindAndModifyOptions {
3333

3434
private @Nullable Collation collation;
3535

36+
private static final FindAndModifyOptions NONE = new FindAndModifyOptions() {
37+
38+
private static final String ERROR_MSG = "FindAndModifyOptions.none() cannot be changed. Please use FindAndModifyOptions.options() instead.";
39+
40+
@Override
41+
public FindAndModifyOptions returnNew(boolean returnNew) {
42+
throw new UnsupportedOperationException(ERROR_MSG);
43+
}
44+
45+
@Override
46+
public FindAndModifyOptions upsert(boolean upsert) {
47+
throw new UnsupportedOperationException(ERROR_MSG);
48+
}
49+
50+
@Override
51+
public FindAndModifyOptions remove(boolean remove) {
52+
throw new UnsupportedOperationException(ERROR_MSG);
53+
}
54+
55+
@Override
56+
public FindAndModifyOptions collation(Collation collation) {
57+
throw new UnsupportedOperationException(ERROR_MSG);
58+
}
59+
};
60+
3661
/**
3762
* Static factory method to create a FindAndModifyOptions instance
3863
*
@@ -42,6 +67,16 @@ public static FindAndModifyOptions options() {
4267
return new FindAndModifyOptions();
4368
}
4469

70+
/**
71+
* Static factory method returning an unmodifiable {@link FindAndModifyOptions} instance.
72+
*
73+
* @return unmodifiable {@link FindAndModifyOptions} instance.
74+
* @since 2.2
75+
*/
76+
public static FindAndModifyOptions none() {
77+
return NONE;
78+
}
79+
4580
/**
4681
* Create new {@link FindAndModifyOptions} based on option of given {@litearl source}.
4782
*

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

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,21 @@ public class FindAndReplaceOptions {
3636
private boolean returnNew;
3737
private boolean upsert;
3838

39+
private static final FindAndReplaceOptions NONE = new FindAndReplaceOptions() {
40+
41+
private static final String ERROR_MSG = "FindAndReplaceOptions.none() cannot be changed. Please use FindAndReplaceOptions.options() instead.";
42+
43+
@Override
44+
public FindAndReplaceOptions returnNew() {
45+
throw new UnsupportedOperationException(ERROR_MSG);
46+
}
47+
48+
@Override
49+
public FindAndReplaceOptions upsert() {
50+
throw new UnsupportedOperationException(ERROR_MSG);
51+
}
52+
};
53+
3954
/**
4055
* Static factory method to create a {@link FindAndReplaceOptions} instance.
4156
* <dl>
@@ -51,6 +66,16 @@ public static FindAndReplaceOptions options() {
5166
return new FindAndReplaceOptions();
5267
}
5368

69+
/**
70+
* Static factory method returning an unmodifiable {@link FindAndReplaceOptions} instance.
71+
*
72+
* @return unmodifiable {@link FindAndReplaceOptions} instance.
73+
* @since 2.2
74+
*/
75+
public static FindAndReplaceOptions none() {
76+
return NONE;
77+
}
78+
5479
/**
5580
* Static factory method to create a {@link FindAndReplaceOptions} instance with
5681
* <dl>

0 commit comments

Comments
 (0)