Skip to content
Open
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
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb-parent</artifactId>
<version>5.1.0-SNAPSHOT</version>
<version>5.1.0-4422-SNAPSHOT</version>
<packaging>pom</packaging>

<name>Spring Data MongoDB</name>
Expand Down
2 changes: 1 addition & 1 deletion spring-data-mongodb-distribution/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
<parent>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb-parent</artifactId>
<version>5.1.0-SNAPSHOT</version>
<version>5.1.0-4422-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

Expand Down
2 changes: 1 addition & 1 deletion spring-data-mongodb/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
<parent>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb-parent</artifactId>
<version>5.1.0-SNAPSHOT</version>
<version>5.1.0-4422-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,26 +16,18 @@
package org.springframework.data.mongodb.core;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import org.bson.Document;
import org.jspecify.annotations.Nullable;
import org.springframework.dao.DataAccessException;

import org.springframework.data.mongodb.MongoDatabaseFactory;
import org.springframework.data.mongodb.UncategorizedMongoDbException;
import org.springframework.data.mongodb.core.convert.QueryMapper;
import org.springframework.data.mongodb.core.index.IndexDefinition;
import org.springframework.data.mongodb.core.index.IndexInfo;
import org.springframework.data.mongodb.core.index.IndexOperations;
import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity;
import org.springframework.data.mongodb.core.mapping.CollectionName;
import org.springframework.util.Assert;
import org.springframework.util.NumberUtils;

import com.mongodb.MongoException;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoCursor;
import com.mongodb.client.model.IndexOptions;

/**
* Default implementation of {@link IndexOperations}.
Expand All @@ -46,133 +38,111 @@
* @author Christoph Strobl
* @author Mark Paluch
*/
public class DefaultIndexOperations implements IndexOperations {

private static final String PARTIAL_FILTER_EXPRESSION_KEY = "partialFilterExpression";

private final String collectionName;
private final QueryMapper mapper;
private final @Nullable Class<?> type;
public class DefaultIndexOperations extends IndexOperationsSupport implements IndexOperations {

private final MongoOperations mongoOperations;

/**
* Creates a new {@link DefaultIndexOperations}.
* Creates a new {@code DefaultIndexOperations}.
*
* @param mongoDbFactory must not be {@literal null}.
* @param collectionName must not be {@literal null}.
* @param queryMapper must not be {@literal null}.
* @deprecated since 2.1. Please use
* {@link DefaultIndexOperations#DefaultIndexOperations(MongoOperations, String, Class)}.
* {@code DefaultIndexOperations#DefaultIndexOperations(MongoOperations, String, Class)}.
*/
@Deprecated
public DefaultIndexOperations(MongoDatabaseFactory mongoDbFactory, String collectionName, QueryMapper queryMapper) {
this(mongoDbFactory, collectionName, queryMapper, null);
}

/**
* Creates a new {@link DefaultIndexOperations}.
* Creates a new {@code DefaultIndexOperations}.
*
* @param mongoDbFactory must not be {@literal null}.
* @param collectionName must not be {@literal null}.
* @param queryMapper must not be {@literal null}.
* @param type Type used for mapping potential partial index filter expression. Can be {@literal null}.
* @since 1.10
* @deprecated since 2.1. Please use
* {@link DefaultIndexOperations#DefaultIndexOperations(MongoOperations, String, Class)}.
* {@code DefaultIndexOperations#DefaultIndexOperations(MongoOperations, String, Class)}.
*/
@Deprecated
public DefaultIndexOperations(MongoDatabaseFactory mongoDbFactory, String collectionName, QueryMapper queryMapper,
@Nullable Class<?> type) {

Assert.notNull(mongoDbFactory, "MongoDbFactory must not be null");
Assert.notNull(collectionName, "Collection name can not be null");
Assert.notNull(queryMapper, "QueryMapper must not be null");

this.collectionName = collectionName;
this.mapper = queryMapper;
this.type = type;
this.mongoOperations = new MongoTemplate(mongoDbFactory);
this(new MongoTemplate(mongoDbFactory), collectionName, queryMapper, type);
}

/**
* Creates a new {@link DefaultIndexOperations}.
* Creates a new {@code DefaultIndexOperations}.
*
* @param mongoOperations must not be {@literal null}.
* @param collectionName must not be {@literal null} or empty.
* @param type can be {@literal null}.
* @since 2.1
*/
public DefaultIndexOperations(MongoOperations mongoOperations, String collectionName, @Nullable Class<?> type) {
this(mongoOperations, CollectionName.just(collectionName), new QueryMapper(mongoOperations.getConverter()), type);
}

Assert.notNull(mongoOperations, "MongoOperations must not be null");
Assert.hasText(collectionName, "Collection name must not be null or empty");
/**
* Creates a new {@code DefaultIndexOperations}.
*
* @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.
* @since 5.1
*/
public DefaultIndexOperations(MongoOperations mongoOperations, String collectionName, QueryMapper queryMapper,
@Nullable Class<?> type) {
this(mongoOperations, CollectionName.just(collectionName), queryMapper, type);
}

/**
* Creates a new {@code DefaultIndexOperations}.
*
* @param mongoOperations must not be {@literal null}.
* @param collectionName must not be {@literal null} or empty.
* @param type can be {@literal null}.
* @since 5.1
*/
protected DefaultIndexOperations(MongoOperations mongoOperations, CollectionName collectionName,
QueryMapper queryMapper, @Nullable Class<?> type) {

super(collectionName, queryMapper, type);

Assert.notNull(mongoOperations, "MongoOperations must not be null");
this.mongoOperations = mongoOperations;
this.mapper = new QueryMapper(mongoOperations.getConverter());
this.collectionName = collectionName;
this.type = type;
}

@Override
@SuppressWarnings("NullAway")
public String createIndex(IndexDefinition indexDefinition) {

return execute(collection -> {

MongoPersistentEntity<?> entity = lookupPersistentEntity(type, collectionName);

IndexOptions indexOptions = IndexConverters.indexDefinitionToIndexOptionsConverter().convert(indexDefinition);

indexOptions = addPartialFilterIfPresent(indexOptions, indexDefinition.getIndexOptions(), entity);
indexOptions = addDefaultCollationIfRequired(indexOptions, entity);

Document mappedKeys = mapper.getMappedSort(indexDefinition.getIndexKeys(), entity);
return collection.createIndex(mappedKeys, indexOptions);
CreateIndexCommand command = toCreateIndexCommand(indexDefinition);
return collection.createIndexes(command.toIndexModels(), command.createIndexOptions()).get(0);
});
}

private @Nullable MongoPersistentEntity<?> lookupPersistentEntity(@Nullable Class<?> entityType, String collection) {

if (entityType != null) {
return mapper.getMappingContext().getRequiredPersistentEntity(entityType);
}

Collection<? extends MongoPersistentEntity<?>> entities = mapper.getMappingContext().getPersistentEntities();

for (MongoPersistentEntity<?> entity : entities) {
if (entity.getCollection().equals(collection)) {
return entity;
}
}

return null;
}

@Override
public void dropIndex(String name) {

execute(collection -> {
collection.dropIndex(name);
return null;
});

}

@Override
@SuppressWarnings("NullAway")
public void alterIndex(String name, org.springframework.data.mongodb.core.index.IndexOptions options) {

Document indexOptions = new Document("name", name);
indexOptions.putAll(options.toDocument());

Document result = mongoOperations
.execute(db -> db.runCommand(new Document("collMod", collectionName).append("index", indexOptions)));
.execute(db -> db.runCommand(alterIndexCommand(name, options), Document.class));

if (NumberUtils.convertNumberToTargetClass(result.get("ok", (Number) 0), Integer.class) != 1) {
throw new UncategorizedMongoDbException(
"Index '%s' could not be modified. Response was %s".formatted(name, result.toJson()), null);
}
validateAlterIndexResponse(name, result);
}

@Override
Expand All @@ -181,62 +151,15 @@ public void dropAllIndexes() {
}

@Override
@SuppressWarnings("NullAway")
public List<IndexInfo> getIndexInfo() {

return execute(new CollectionCallback<List<IndexInfo>>() {

public List<IndexInfo> doInCollection(MongoCollection<Document> collection)
throws MongoException, DataAccessException {

MongoCursor<Document> cursor = collection.listIndexes(Document.class).iterator();
return getIndexData(cursor);
}

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

int available = cursor.available();
List<IndexInfo> indexInfoList = available > 0 ? new ArrayList<>(available) : new ArrayList<>();

while (cursor.hasNext()) {

Document ix = cursor.next();
IndexInfo indexInfo = IndexConverters.documentToIndexInfoConverter().convert(ix);
indexInfoList.add(indexInfo);
}

return indexInfoList;
}
});
}

public <T> @Nullable T execute(CollectionCallback<T> callback) {

Assert.notNull(callback, "CollectionCallback must not be null");

return mongoOperations.execute(collectionName, callback);
}

private IndexOptions addPartialFilterIfPresent(IndexOptions ops, Document sourceOptions,
@Nullable MongoPersistentEntity<?> entity) {

if (!sourceOptions.containsKey(PARTIAL_FILTER_EXPRESSION_KEY)) {
return ops;
}

Assert.isInstanceOf(Document.class, sourceOptions.get(PARTIAL_FILTER_EXPRESSION_KEY));
return ops.partialFilterExpression(
mapper.getMappedSort((Document) sourceOptions.get(PARTIAL_FILTER_EXPRESSION_KEY), entity));
return execute(
collection -> collection.listIndexes(Document.class).map(IndexInfo::indexInfoOf).into(new ArrayList<>()));
}

@SuppressWarnings("NullAway")
private static IndexOptions addDefaultCollationIfRequired(IndexOptions ops,
@Nullable MongoPersistentEntity<?> entity) {

if (ops.getCollation() != null || entity == null || !entity.hasCollation()) {
return ops;
}
public <T> T execute(CollectionCallback<T> callback) {

return ops.collation(entity.getCollation().toMongoCollation());
Assert.notNull(callback, "CollectionCallback must not be null");
return mongoOperations.execute(getCollectionName(), callback);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ class DefaultIndexOperationsProvider implements IndexOperationsProvider {
}

@Override
public IndexOperations indexOps(String collectionName, @Nullable Class<?> type) {
return new DefaultIndexOperations(mongoDbFactory, collectionName, mapper, type);
public IndexOperations indexOps(String collectionName, @Nullable Class<?> entityClass) {
return new DefaultIndexOperations(mongoDbFactory, collectionName, mapper, entityClass);
}
}
Loading
Loading