Browse Source

Merge 80bb716250 into 65eddcc17d

pull/5172/merge
이성혁 5 days ago committed by GitHub
parent
commit
4835f4d80c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 23
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/DefaultIndexOperations.java
  2. 24
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/DefaultReactiveIndexOperations.java
  3. 49
      spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultIndexOperationsUnitTests.java
  4. 43
      spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultReactiveIndexOperationsUnitTests.java

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

@ -35,6 +35,8 @@ import org.springframework.util.NumberUtils; @@ -35,6 +35,8 @@ import org.springframework.util.NumberUtils;
import com.mongodb.MongoException;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoCursor;
import com.mongodb.client.model.CreateIndexOptions;
import com.mongodb.client.model.IndexModel;
import com.mongodb.client.model.IndexOptions;
/**
@ -53,6 +55,7 @@ public class DefaultIndexOperations implements IndexOperations { @@ -53,6 +55,7 @@ public class DefaultIndexOperations implements IndexOperations {
private final String collectionName;
private final QueryMapper mapper;
private final @Nullable Class<?> type;
private final CreateIndexOptions createIndexOptions;
private final MongoOperations mongoOperations;
@ -92,6 +95,7 @@ public class DefaultIndexOperations implements IndexOperations { @@ -92,6 +95,7 @@ public class DefaultIndexOperations implements IndexOperations {
this.collectionName = collectionName;
this.mapper = queryMapper;
this.type = type;
this.createIndexOptions = new CreateIndexOptions();
this.mongoOperations = new MongoTemplate(mongoDbFactory);
}
@ -104,14 +108,30 @@ public class DefaultIndexOperations implements IndexOperations { @@ -104,14 +108,30 @@ public class DefaultIndexOperations implements IndexOperations {
* @since 2.1
*/
public DefaultIndexOperations(MongoOperations mongoOperations, String collectionName, @Nullable Class<?> type) {
this(mongoOperations, collectionName, type, new CreateIndexOptions());
}
/**
* Creates a new {@link DefaultIndexOperations}.
*
* @param mongoOperations must not be {@literal null}.
* @param collectionName must not be {@literal null} or empty.
* @param type can be {@literal null}.
* @param createIndexOptions must not be {@literal null}.
* @since 4.5
*/
public DefaultIndexOperations(MongoOperations mongoOperations, String collectionName, @Nullable Class<?> type,
CreateIndexOptions createIndexOptions) {
Assert.notNull(mongoOperations, "MongoOperations must not be null");
Assert.hasText(collectionName, "Collection name must not be null or empty");
Assert.notNull(createIndexOptions, "CreateIndexOptions must not be null");
this.mongoOperations = mongoOperations;
this.mapper = new QueryMapper(mongoOperations.getConverter());
this.collectionName = collectionName;
this.type = type;
this.createIndexOptions = createIndexOptions;
}
@Override
@ -128,7 +148,8 @@ public class DefaultIndexOperations implements IndexOperations { @@ -128,7 +148,8 @@ public class DefaultIndexOperations implements IndexOperations {
indexOptions = addDefaultCollationIfRequired(indexOptions, entity);
Document mappedKeys = mapper.getMappedSort(indexDefinition.getIndexKeys(), entity);
return collection.createIndex(mappedKeys, indexOptions);
IndexModel indexModel = new IndexModel(mappedKeys, indexOptions);
return collection.createIndexes(List.of(indexModel), createIndexOptions).get(0);
});
}

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

@ -19,6 +19,7 @@ import reactor.core.publisher.Flux; @@ -19,6 +19,7 @@ import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import java.util.Collection;
import java.util.List;
import org.bson.Document;
import org.jspecify.annotations.Nullable;
@ -31,6 +32,8 @@ import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity; @@ -31,6 +32,8 @@ import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity;
import org.springframework.util.Assert;
import org.springframework.util.NumberUtils;
import com.mongodb.client.model.CreateIndexOptions;
import com.mongodb.client.model.IndexModel;
import com.mongodb.client.model.IndexOptions;
/**
@ -48,6 +51,7 @@ public class DefaultReactiveIndexOperations implements ReactiveIndexOperations { @@ -48,6 +51,7 @@ public class DefaultReactiveIndexOperations implements ReactiveIndexOperations {
private final String collectionName;
private final QueryMapper queryMapper;
private final @Nullable Class<?> type;
private final CreateIndexOptions createIndexOptions;
/**
* Creates a new {@link DefaultReactiveIndexOperations}.
@ -71,15 +75,32 @@ public class DefaultReactiveIndexOperations implements ReactiveIndexOperations { @@ -71,15 +75,32 @@ public class DefaultReactiveIndexOperations implements ReactiveIndexOperations {
*/
public DefaultReactiveIndexOperations(ReactiveMongoOperations mongoOperations, String collectionName,
QueryMapper queryMapper, @Nullable Class<?> type) {
this(mongoOperations, collectionName, queryMapper, type, new CreateIndexOptions());
}
/**
* Creates a new {@link DefaultReactiveIndexOperations}.
*
* @param mongoOperations must not be {@literal null}.
* @param collectionName must not be {@literal null}.
* @param queryMapper must not be {@literal null}.
* @param type used for mapping potential partial index filter expression, must not be {@literal null}.
* @param createIndexOptions must not be {@literal null}.
* @since 4.5
*/
public DefaultReactiveIndexOperations(ReactiveMongoOperations mongoOperations, String collectionName,
QueryMapper queryMapper, @Nullable Class<?> type, CreateIndexOptions createIndexOptions) {
Assert.notNull(mongoOperations, "ReactiveMongoOperations must not be null");
Assert.notNull(collectionName, "Collection must not be null");
Assert.notNull(queryMapper, "QueryMapper must not be null");
Assert.notNull(createIndexOptions, "CreateIndexOptions must not be null");
this.mongoOperations = mongoOperations;
this.collectionName = collectionName;
this.queryMapper = queryMapper;
this.type = type;
this.createIndexOptions = createIndexOptions;
}
@Override
@ -95,7 +116,8 @@ public class DefaultReactiveIndexOperations implements ReactiveIndexOperations { @@ -95,7 +116,8 @@ public class DefaultReactiveIndexOperations implements ReactiveIndexOperations {
indexOptions = addPartialFilterIfPresent(indexOptions, indexDefinition.getIndexOptions(), entity);
indexOptions = addDefaultCollationIfRequired(indexOptions, entity);
return collection.createIndex(indexDefinition.getIndexKeys(), indexOptions);
IndexModel indexModel = new IndexModel(indexDefinition.getIndexKeys(), indexOptions);
return collection.createIndexes(List.of(indexModel), createIndexOptions);
}).next();
}

49
spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultIndexOperationsUnitTests.java

@ -16,8 +16,11 @@ @@ -16,8 +16,11 @@
package org.springframework.data.mongodb.core;
import static org.assertj.core.api.Assertions.*;
import static org.mockito.ArgumentMatchers.*;
import static org.mockito.Mockito.*;
import java.util.List;
import org.bson.Document;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@ -37,6 +40,8 @@ import org.springframework.data.mongodb.core.query.Collation; @@ -37,6 +40,8 @@ import org.springframework.data.mongodb.core.query.Collation;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import com.mongodb.client.model.CreateIndexOptions;
import com.mongodb.client.model.IndexModel;
import com.mongodb.client.model.IndexOptions;
/**
@ -64,7 +69,7 @@ public class DefaultIndexOperationsUnitTests { @@ -64,7 +69,7 @@ public class DefaultIndexOperationsUnitTests {
when(factory.getMongoDatabase()).thenReturn(db);
when(factory.getExceptionTranslator()).thenReturn(exceptionTranslator);
when(db.getCollection(any(), any(Class.class))).thenReturn(collection);
when(collection.createIndex(any(), any(IndexOptions.class))).thenReturn("OK");
when(collection.createIndexes(anyList(), any(CreateIndexOptions.class))).thenReturn(List.of("OK"));
this.mappingContext = new MongoMappingContext();
this.converter = spy(new MappingMongoConverter(new DefaultDbRefResolver(factory), mappingContext));
@ -76,7 +81,9 @@ public class DefaultIndexOperationsUnitTests { @@ -76,7 +81,9 @@ public class DefaultIndexOperationsUnitTests {
indexOpsFor(Jedi.class).ensureIndex(new Index("name", Direction.DESC));
verify(collection).createIndex(eq(new Document("firstname", -1)), any());
ArgumentCaptor<List<IndexModel>> captor = ArgumentCaptor.forClass(List.class);
verify(collection).createIndexes(captor.capture(), any(CreateIndexOptions.class));
assertThat(captor.getValue().get(0).getKeys()).isEqualTo(new Document("firstname", -1));
}
@Test // DATAMONGO-1854
@ -84,10 +91,10 @@ public class DefaultIndexOperationsUnitTests { @@ -84,10 +91,10 @@ public class DefaultIndexOperationsUnitTests {
indexOpsFor(Jedi.class).ensureIndex(new Index("firstname", Direction.DESC));
ArgumentCaptor<IndexOptions> options = ArgumentCaptor.forClass(IndexOptions.class);
verify(collection).createIndex(any(), options.capture());
ArgumentCaptor<List<IndexModel>> captor = ArgumentCaptor.forClass(List.class);
verify(collection).createIndexes(captor.capture(), any(CreateIndexOptions.class));
assertThat(options.getValue().getCollation()).isNull();
assertThat(captor.getValue().get(0).getOptions().getCollation()).isNull();
}
@Test // DATAMONGO-1854
@ -95,10 +102,10 @@ public class DefaultIndexOperationsUnitTests { @@ -95,10 +102,10 @@ public class DefaultIndexOperationsUnitTests {
indexOpsFor(Sith.class).ensureIndex(new Index("firstname", Direction.DESC));
ArgumentCaptor<IndexOptions> options = ArgumentCaptor.forClass(IndexOptions.class);
verify(collection).createIndex(any(), options.capture());
ArgumentCaptor<List<IndexModel>> captor = ArgumentCaptor.forClass(List.class);
verify(collection).createIndexes(captor.capture(), any(CreateIndexOptions.class));
assertThat(options.getValue().getCollation())
assertThat(captor.getValue().get(0).getOptions().getCollation())
.isEqualTo(com.mongodb.client.model.Collation.builder().locale("de_AT").build());
}
@ -107,10 +114,10 @@ public class DefaultIndexOperationsUnitTests { @@ -107,10 +114,10 @@ public class DefaultIndexOperationsUnitTests {
indexOpsFor(Sith.class).ensureIndex(new Index("firstname", Direction.DESC).collation(Collation.of("en_US")));
ArgumentCaptor<IndexOptions> options = ArgumentCaptor.forClass(IndexOptions.class);
verify(collection).createIndex(any(), options.capture());
ArgumentCaptor<List<IndexModel>> captor = ArgumentCaptor.forClass(List.class);
verify(collection).createIndexes(captor.capture(), any(CreateIndexOptions.class));
assertThat(options.getValue().getCollation())
assertThat(captor.getValue().get(0).getOptions().getCollation())
.isEqualTo(com.mongodb.client.model.Collation.builder().locale("en_US").build());
}
@ -119,7 +126,9 @@ public class DefaultIndexOperationsUnitTests { @@ -119,7 +126,9 @@ public class DefaultIndexOperationsUnitTests {
indexOpsFor(Jedi.class).ensureIndex(HashedIndex.hashed("name"));
verify(collection).createIndex(eq(new Document("firstname", "hashed")), any());
ArgumentCaptor<List<IndexModel>> captor = ArgumentCaptor.forClass(List.class);
verify(collection).createIndexes(captor.capture(), any(CreateIndexOptions.class));
assertThat(captor.getValue().get(0).getKeys()).isEqualTo(new Document("firstname", "hashed"));
}
@Test // GH-4698
@ -131,6 +140,22 @@ public class DefaultIndexOperationsUnitTests { @@ -131,6 +140,22 @@ public class DefaultIndexOperationsUnitTests {
verify(db).getCollection(eq("foo"), any(Class.class));
}
@Test // GH-4422
void shouldPassCreateIndexOptionsToDriver() {
CreateIndexOptions createIndexOptions = new CreateIndexOptions()
.commitQuorum(com.mongodb.CreateIndexCommitQuorum.MAJORITY);
DefaultIndexOperations operations = new DefaultIndexOperations(template, template.getCollectionName(Jedi.class),
Jedi.class, createIndexOptions);
operations.createIndex(new Index("name", Direction.DESC));
ArgumentCaptor<CreateIndexOptions> optionsCaptor = ArgumentCaptor.forClass(CreateIndexOptions.class);
verify(collection).createIndexes(anyList(), optionsCaptor.capture());
assertThat(optionsCaptor.getValue()).isSameAs(createIndexOptions);
}
private DefaultIndexOperations indexOpsFor(Class<?> type) {
return new DefaultIndexOperations(template, template.getCollectionName(type), type);
}

43
spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultReactiveIndexOperationsUnitTests.java

@ -16,10 +16,14 @@ @@ -16,10 +16,14 @@
package org.springframework.data.mongodb.core;
import static org.assertj.core.api.Assertions.*;
import static org.mockito.ArgumentMatchers.*;
import static org.mockito.Mockito.*;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import java.util.List;
import org.bson.Document;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@ -38,6 +42,8 @@ import org.springframework.data.mongodb.core.mapping.Field; @@ -38,6 +42,8 @@ import org.springframework.data.mongodb.core.mapping.Field;
import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
import org.springframework.data.mongodb.core.query.Collation;
import com.mongodb.client.model.CreateIndexOptions;
import com.mongodb.client.model.IndexModel;
import com.mongodb.client.model.IndexOptions;
import com.mongodb.reactivestreams.client.MongoCollection;
import com.mongodb.reactivestreams.client.MongoDatabase;
@ -66,7 +72,7 @@ public class DefaultReactiveIndexOperationsUnitTests { @@ -66,7 +72,7 @@ public class DefaultReactiveIndexOperationsUnitTests {
when(factory.getMongoDatabase()).thenReturn(Mono.just(db));
when(factory.getExceptionTranslator()).thenReturn(exceptionTranslator);
when(db.getCollection(any(), any(Class.class))).thenReturn(collection);
when(collection.createIndex(any(), any(IndexOptions.class))).thenReturn(publisher);
when(collection.createIndexes(anyList(), any(CreateIndexOptions.class))).thenReturn(Flux.just("OK"));
this.mappingContext = new MongoMappingContext();
this.converter = spy(new MappingMongoConverter(NoOpDbRefResolver.INSTANCE, mappingContext));
@ -78,10 +84,10 @@ public class DefaultReactiveIndexOperationsUnitTests { @@ -78,10 +84,10 @@ public class DefaultReactiveIndexOperationsUnitTests {
indexOpsFor(Jedi.class).ensureIndex(new Index("firstname", Direction.DESC)).subscribe();
ArgumentCaptor<IndexOptions> options = ArgumentCaptor.forClass(IndexOptions.class);
verify(collection).createIndex(any(), options.capture());
ArgumentCaptor<List<IndexModel>> captor = ArgumentCaptor.forClass(List.class);
verify(collection).createIndexes(captor.capture(), any(CreateIndexOptions.class));
assertThat(options.getValue().getCollation()).isNull();
assertThat(captor.getValue().get(0).getOptions().getCollation()).isNull();
}
@Test // DATAMONGO-1854
@ -89,10 +95,10 @@ public class DefaultReactiveIndexOperationsUnitTests { @@ -89,10 +95,10 @@ public class DefaultReactiveIndexOperationsUnitTests {
indexOpsFor(Sith.class).ensureIndex(new Index("firstname", Direction.DESC)).subscribe();
ArgumentCaptor<IndexOptions> options = ArgumentCaptor.forClass(IndexOptions.class);
verify(collection).createIndex(any(), options.capture());
ArgumentCaptor<List<IndexModel>> captor = ArgumentCaptor.forClass(List.class);
verify(collection).createIndexes(captor.capture(), any(CreateIndexOptions.class));
assertThat(options.getValue().getCollation())
assertThat(captor.getValue().get(0).getOptions().getCollation())
.isEqualTo(com.mongodb.client.model.Collation.builder().locale("de_AT").build());
}
@ -102,13 +108,30 @@ public class DefaultReactiveIndexOperationsUnitTests { @@ -102,13 +108,30 @@ public class DefaultReactiveIndexOperationsUnitTests {
indexOpsFor(Sith.class).ensureIndex(new Index("firstname", Direction.DESC).collation(Collation.of("en_US")))
.subscribe();
ArgumentCaptor<IndexOptions> options = ArgumentCaptor.forClass(IndexOptions.class);
verify(collection).createIndex(any(), options.capture());
ArgumentCaptor<List<IndexModel>> captor = ArgumentCaptor.forClass(List.class);
verify(collection).createIndexes(captor.capture(), any(CreateIndexOptions.class));
assertThat(options.getValue().getCollation())
assertThat(captor.getValue().get(0).getOptions().getCollation())
.isEqualTo(com.mongodb.client.model.Collation.builder().locale("en_US").build());
}
@Test // GH-4422
void shouldPassCreateIndexOptionsToDriver() {
CreateIndexOptions createIndexOptions = new CreateIndexOptions()
.commitQuorum(com.mongodb.CreateIndexCommitQuorum.MAJORITY);
DefaultReactiveIndexOperations operations = new DefaultReactiveIndexOperations(template,
template.getCollectionName(Jedi.class), new QueryMapper(template.getConverter()), Jedi.class,
createIndexOptions);
operations.ensureIndex(new Index("firstname", Direction.DESC)).subscribe();
ArgumentCaptor<CreateIndexOptions> optionsCaptor = ArgumentCaptor.forClass(CreateIndexOptions.class);
verify(collection).createIndexes(anyList(), optionsCaptor.capture());
assertThat(optionsCaptor.getValue()).isSameAs(createIndexOptions);
}
private DefaultReactiveIndexOperations indexOpsFor(Class<?> type) {
return new DefaultReactiveIndexOperations(template, template.getCollectionName(type),
new QueryMapper(template.getConverter()), type);

Loading…
Cancel
Save