DATAMONGO-2316 - Configure simple collation on resolved text-indexes for non-simple collation Collections.
We now configure resolved text-indexes with a simple collation when the text index is created in a collection that uses a non-simple collation. This explicit setting is required by MongoDB to properly create a text index. Previously, index creation failed.
This commit is contained in:
@@ -33,6 +33,7 @@ import java.util.stream.Collectors;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.mapping.Association;
|
||||
@@ -41,13 +42,13 @@ import org.springframework.data.mapping.MappingException;
|
||||
import org.springframework.data.mapping.PersistentEntity;
|
||||
import org.springframework.data.mapping.PersistentProperty;
|
||||
import org.springframework.data.mapping.PropertyHandler;
|
||||
import org.springframework.data.mapping.context.MappingContext;
|
||||
import org.springframework.data.mongodb.core.index.MongoPersistentEntityIndexResolver.CycleGuard.Path;
|
||||
import org.springframework.data.mongodb.core.index.MongoPersistentEntityIndexResolver.TextIndexIncludeOptions.IncludeStrategy;
|
||||
import org.springframework.data.mongodb.core.index.TextIndexDefinition.TextIndexDefinitionBuilder;
|
||||
import org.springframework.data.mongodb.core.index.TextIndexDefinition.TextIndexedFieldSpec;
|
||||
import org.springframework.data.mongodb.core.mapping.BasicMongoPersistentEntity;
|
||||
import org.springframework.data.mongodb.core.mapping.Document;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
|
||||
import org.springframework.data.spel.EvaluationContextProvider;
|
||||
@@ -80,7 +81,7 @@ public class MongoPersistentEntityIndexResolver implements IndexResolver {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(MongoPersistentEntityIndexResolver.class);
|
||||
private static final SpelExpressionParser PARSER = new SpelExpressionParser();
|
||||
|
||||
private final MongoMappingContext mappingContext;
|
||||
private final MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentProperty> mappingContext;
|
||||
private EvaluationContextProvider evaluationContextProvider = EvaluationContextProvider.DEFAULT;
|
||||
|
||||
/**
|
||||
@@ -88,7 +89,8 @@ public class MongoPersistentEntityIndexResolver implements IndexResolver {
|
||||
*
|
||||
* @param mappingContext must not be {@literal null}.
|
||||
*/
|
||||
public MongoPersistentEntityIndexResolver(MongoMappingContext mappingContext) {
|
||||
public MongoPersistentEntityIndexResolver(
|
||||
MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentProperty> mappingContext) {
|
||||
|
||||
Assert.notNull(mappingContext, "Mapping context must not be null in order to resolve index definitions");
|
||||
this.mappingContext = mappingContext;
|
||||
@@ -261,6 +263,10 @@ public class MongoPersistentEntityIndexResolver implements IndexResolver {
|
||||
LOGGER.info(e.getMessage());
|
||||
}
|
||||
|
||||
if (root.hasCollation()) {
|
||||
indexDefinitionBuilder.withSimpleCollation();
|
||||
}
|
||||
|
||||
TextIndexDefinition indexDefinition = indexDefinitionBuilder.build();
|
||||
|
||||
if (!indexDefinition.hasFieldSpec()) {
|
||||
|
||||
@@ -21,6 +21,7 @@ import java.util.Set;
|
||||
|
||||
import org.bson.Document;
|
||||
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
||||
import org.springframework.data.mongodb.core.query.Collation;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
@@ -40,9 +41,10 @@ public class TextIndexDefinition implements IndexDefinition {
|
||||
private @Nullable String defaultLanguage;
|
||||
private @Nullable String languageOverride;
|
||||
private @Nullable IndexFilter filter;
|
||||
private @Nullable Collation collation;
|
||||
|
||||
TextIndexDefinition() {
|
||||
fieldSpecs = new LinkedHashSet<TextIndexedFieldSpec>();
|
||||
fieldSpecs = new LinkedHashSet<>();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -116,6 +118,10 @@ public class TextIndexDefinition implements IndexDefinition {
|
||||
options.put("default_language", defaultLanguage);
|
||||
}
|
||||
|
||||
if (collation != null) {
|
||||
options.put("collation", collation.toDocument());
|
||||
}
|
||||
|
||||
Document weightsDocument = new Document();
|
||||
for (TextIndexedFieldSpec fieldSpec : fieldSpecs) {
|
||||
if (fieldSpec.isWeighted()) {
|
||||
@@ -348,6 +354,17 @@ public class TextIndexDefinition implements IndexDefinition {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure to use simple {@link Collation}. Required if the collection uses a non-simple collation.
|
||||
*
|
||||
* @since 2.2
|
||||
*/
|
||||
public TextIndexDefinitionBuilder withSimpleCollation() {
|
||||
|
||||
this.instance.collation = Collation.simple();
|
||||
return this;
|
||||
}
|
||||
|
||||
public TextIndexDefinition build() {
|
||||
return this.instance;
|
||||
}
|
||||
|
||||
@@ -744,16 +744,28 @@ public class MongoPersistentEntityIndexResolverUnitTests {
|
||||
|
||||
assertThat(indexDefinitions).hasSize(1);
|
||||
assertIndexPathAndCollection("bar", "textIndexOnSinglePropertyInRoot", indexDefinitions.get(0));
|
||||
assertThat(indexDefinitions.get(0).getIndexOptions()).doesNotContainKey("collation");
|
||||
}
|
||||
|
||||
@Test // DATAMONGO-2316
|
||||
public void shouldEnforceSimpleCollationOnTextIndex() {
|
||||
|
||||
List<IndexDefinitionHolder> indexDefinitions = prepareMappingContextAndResolveIndexForType(
|
||||
TextIndexWithCollation.class);
|
||||
|
||||
assertThat(indexDefinitions).hasSize(1);
|
||||
assertThat(indexDefinitions.get(0).getIndexOptions()).containsEntry("collation",
|
||||
new org.bson.Document("locale", "simple"));
|
||||
}
|
||||
|
||||
@Test // DATAMONGO-937
|
||||
public void shouldResolveMultiFieldTextIndexCorrectly() {
|
||||
|
||||
List<IndexDefinitionHolder> indexDefinitions = prepareMappingContextAndResolveIndexForType(
|
||||
TextIndexOnMutiplePropertiesInRoot.class);
|
||||
TextIndexOnMultiplePropertiesInRoot.class);
|
||||
|
||||
assertThat(indexDefinitions).hasSize(1);
|
||||
assertIndexPathAndCollection(new String[] { "foo", "bar" }, "textIndexOnMutiplePropertiesInRoot",
|
||||
assertIndexPathAndCollection(new String[] { "foo", "bar" }, "textIndexOnMultiplePropertiesInRoot",
|
||||
indexDefinitions.get(0));
|
||||
}
|
||||
|
||||
@@ -862,8 +874,14 @@ public class MongoPersistentEntityIndexResolverUnitTests {
|
||||
@TextIndexed String bar;
|
||||
}
|
||||
|
||||
@Document(collation = "de_AT")
|
||||
static class TextIndexWithCollation {
|
||||
|
||||
@TextIndexed String foo;
|
||||
}
|
||||
|
||||
@Document
|
||||
static class TextIndexOnMutiplePropertiesInRoot {
|
||||
static class TextIndexOnMultiplePropertiesInRoot {
|
||||
|
||||
@TextIndexed String foo;
|
||||
|
||||
|
||||
@@ -22,12 +22,15 @@ import java.util.List;
|
||||
import org.junit.Before;
|
||||
import org.junit.ClassRule;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Sort.Direction;
|
||||
import org.springframework.data.mongodb.config.AbstractIntegrationTests;
|
||||
import org.springframework.data.mongodb.core.CollectionOptions;
|
||||
import org.springframework.data.mongodb.core.MongoTemplate;
|
||||
import org.springframework.data.mongodb.core.mapping.Document;
|
||||
import org.springframework.data.mongodb.core.mapping.Language;
|
||||
import org.springframework.data.mongodb.core.query.Collation;
|
||||
import org.springframework.data.mongodb.test.util.MongoVersionRule;
|
||||
import org.springframework.data.util.Version;
|
||||
|
||||
@@ -35,6 +38,7 @@ import com.mongodb.WriteConcern;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public class TextIndexTests extends AbstractIntegrationTests {
|
||||
|
||||
@@ -48,11 +52,21 @@ public class TextIndexTests extends AbstractIntegrationTests {
|
||||
|
||||
template.setWriteConcern(WriteConcern.JOURNALED);
|
||||
this.indexOps = template.indexOps(TextIndexedDocumentRoot.class);
|
||||
|
||||
template.dropCollection(TextIndexedDocumentRoot.class);
|
||||
template.createCollection(TextIndexedDocumentRoot.class,
|
||||
CollectionOptions.empty().collation(Collation.of("de_AT")));
|
||||
}
|
||||
|
||||
@Test // DATAMONGO-937
|
||||
@Test // DATAMONGO-937, DATAMONGO-2316
|
||||
public void indexInfoShouldHaveBeenCreatedCorrectly() {
|
||||
|
||||
IndexResolver indexResolver = IndexResolver.create(template.getConverter().getMappingContext());
|
||||
|
||||
for (IndexDefinition indexDefinition : indexResolver.resolveIndexFor(TextIndexedDocumentRoot.class)) {
|
||||
indexOps.ensureIndex(indexDefinition);
|
||||
}
|
||||
|
||||
List<IndexInfo> indexInfos = indexOps.getIndexInfo();
|
||||
|
||||
assertThat(indexInfos.size()).isEqualTo(2);
|
||||
@@ -69,16 +83,16 @@ public class TextIndexTests extends AbstractIntegrationTests {
|
||||
assertThat(textIndexInfo.getLanguage()).isEqualTo("spanish");
|
||||
}
|
||||
|
||||
@Document(language = "spanish")
|
||||
@Document(language = "spanish", collation = "de_AT")
|
||||
static class TextIndexedDocumentRoot {
|
||||
|
||||
@TextIndexed String textIndexedPropertyWithDefaultWeight;
|
||||
@TextIndexed(weight = 5) String textIndexedPropertyWithWeight;
|
||||
|
||||
TextIndexedDocumentWihtLanguageOverride nestedDocument;
|
||||
TextIndexedDocumentWithLanguageOverride nestedDocument;
|
||||
}
|
||||
|
||||
static class TextIndexedDocumentWihtLanguageOverride {
|
||||
static class TextIndexedDocumentWithLanguageOverride {
|
||||
|
||||
@Language String lang;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user