DATAMONGO-2218 - Add support for replaceOne operation in BulkOperations.

Original Pull Request: #655
This commit is contained in:
Minsu
2019-03-03 03:28:13 +09:00
committed by Christoph Strobl
parent 24677fabd1
commit f3b7ce8079
4 changed files with 108 additions and 16 deletions

View File

@@ -31,6 +31,7 @@ import com.mongodb.bulk.BulkWriteResult;
*
* @author Tobias Trelle
* @author Oliver Gierke
* @author Minsu Kim
* @since 1.9
*/
public interface BulkOperations {
@@ -135,6 +136,15 @@ public interface BulkOperations {
*/
BulkOperations remove(List<Query> removes);
/**
* Add a single replace operation to the bulk operation.
*
* @param query Update criteria.
* @param document the document to replace, must not be {@literal null}.
* @return the current {@link BulkOperations} instance with the replace added, will never be {@literal null}.
*/
BulkOperations replaceOne(Query query, Object document);
/**
* Execute all bulk operations using the default write concern.
*

View File

@@ -26,7 +26,6 @@ import java.util.stream.Collectors;
import org.bson.Document;
import org.bson.conversions.Bson;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.support.PersistenceExceptionTranslator;
import org.springframework.data.mongodb.core.convert.QueryMapper;
import org.springframework.data.mongodb.core.convert.UpdateMapper;
@@ -38,18 +37,8 @@ import org.springframework.data.util.Pair;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import com.mongodb.BulkWriteException;
import com.mongodb.WriteConcern;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.model.BulkWriteOptions;
import com.mongodb.client.model.DeleteManyModel;
import com.mongodb.client.model.DeleteOneModel;
import com.mongodb.client.model.DeleteOptions;
import com.mongodb.client.model.InsertOneModel;
import com.mongodb.client.model.UpdateManyModel;
import com.mongodb.client.model.UpdateOneModel;
import com.mongodb.client.model.UpdateOptions;
import com.mongodb.client.model.WriteModel;
import com.mongodb.client.model.*;
/**
* Default implementation for {@link BulkOperations}.
@@ -58,6 +47,7 @@ import com.mongodb.client.model.WriteModel;
* @author Oliver Gierke
* @author Christoph Strobl
* @author Mark Paluch
* @author Minsu Kim
* @since 1.9
*/
class DefaultBulkOperations implements BulkOperations {
@@ -266,6 +256,32 @@ class DefaultBulkOperations implements BulkOperations {
return this;
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.BulkOperations#replaceOne(org.springframework.data.mongodb.core.query.Query, java.lang.Object)
*/
@Override
public BulkOperations replaceOne(Query query, Object document) {
Assert.notNull(query, "Query must not be null!");
Assert.notNull(document, "Document must not be null!");
ReplaceOptions replaceOptions = new ReplaceOptions();
query.getCollation().map(Collation::toMongoCollation).ifPresent(replaceOptions::collation);
Bson mappedQuery = getMappedQuery(query.getQueryObject());
if (document instanceof Document) {
models.add(new ReplaceOneModel<>(mappedQuery, (Document) document, replaceOptions));
return this;
}
Document sink = new Document();
mongoOperations.getConverter().write(document, sink);
models.add(new ReplaceOneModel<>(mappedQuery, sink, replaceOptions));
return this;
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.BulkOperations#executeBulk()

View File

@@ -53,6 +53,7 @@ import com.mongodb.client.MongoCollection;
* @author Tobias Trelle
* @author Oliver Gierke
* @author Christoph Strobl
* @author Minsu Kim
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:infrastructure.xml")
@@ -200,6 +201,31 @@ public class DefaultBulkOperationsIntegrationTests {
testRemove(BulkMode.UNORDERED);
}
@Test // DATAMONGO-2218
public void replaceOneOrdered() {
testReplaceOne(BulkMode.ORDERED);
}
@Test // DATAMONGO-2218
public void replaceOneUnordered() {
testReplaceOne(BulkMode.UNORDERED);
}
@Test // DATAMONGO-2218
public void replaceOneDoesReplace() {
insertSomeDocuments();
com.mongodb.bulk.BulkWriteResult result = createBulkOps(BulkMode.ORDERED).//
replaceOne(where("_id", "1"), rawDoc("1", "value2")).//
execute();
assertThat(result, notNullValue());
assertThat(result.getMatchedCount(), is(1));
assertThat(result.getModifiedCount(), is(1));
assertThat(result.getInsertedCount(), is(0));
}
/**
* If working on the same set of documents, only an ordered bulk operation will yield predictable results.
*/
@@ -278,6 +304,19 @@ public class DefaultBulkOperationsIntegrationTests {
assertThat(createBulkOps(mode).remove(removes).execute().getDeletedCount(), is(3));
}
private void testReplaceOne(BulkMode mode) {
BulkOperations bulkOps = createBulkOps(mode);
insertSomeDocuments();
Query query = where("_id", "1");
Document document = rawDoc("1", "value2");
int modifiedCount = bulkOps.replaceOne(query, document).execute().getModifiedCount();
assertThat(modifiedCount, is(1));
}
private BulkOperations createBulkOps(BulkMode mode) {
return createBulkOps(mode, null);
}

View File

@@ -26,6 +26,7 @@ import static org.springframework.data.mongodb.core.query.Query.*;
import java.util.List;
import java.util.Optional;
import com.mongodb.client.model.*;
import org.bson.Document;
import org.junit.Before;
import org.junit.Test;
@@ -51,16 +52,13 @@ import org.springframework.data.mongodb.core.query.Update;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import com.mongodb.client.model.DeleteManyModel;
import com.mongodb.client.model.UpdateManyModel;
import com.mongodb.client.model.UpdateOneModel;
import com.mongodb.client.model.WriteModel;
/**
* Unit tests for {@link DefaultBulkOperations}.
*
* @author Christoph Strobl
* @author Mark Paluch
* @author Minsu Kim
*/
@RunWith(MockitoJUnitRunner.class)
public class DefaultBulkOperationsUnitTests {
@@ -133,6 +131,18 @@ public class DefaultBulkOperationsUnitTests {
.isEqualTo(com.mongodb.client.model.Collation.builder().locale("de").build());
}
@Test // DATAMONGO-2218
public void replaceOneShouldUseCollationWhenPresent() {
ops.replaceOne(new BasicQuery("{}").collation(Collation.of("de")), new SomeDomainType()).execute();
verify(collection).bulkWrite(captor.capture(), any());
assertThat(captor.getValue().get(0)).isInstanceOf(ReplaceOneModel.class);
assertThat(((ReplaceOneModel<Document>) captor.getValue().get(0)).getReplaceOptions().getCollation())
.isEqualTo(com.mongodb.client.model.Collation.builder().locale("de").build());
}
@Test // DATAMONGO-1678
public void bulkUpdateShouldMapQueryAndUpdateCorrectly() {
@@ -156,6 +166,23 @@ public class DefaultBulkOperationsUnitTests {
assertThat(updateModel.getFilter()).isEqualTo(new Document("first_name", "danerys"));
}
@Test // DATAMONGO-2218
public void bulkReplaceOneShouldMapQueryCorrectly() {
SomeDomainType replacement = new SomeDomainType();
replacement.firstName = "Minsu";
replacement.lastName = "Kim";
ops.replaceOne(query(where("firstName").is("danerys")), replacement).execute();
verify(collection).bulkWrite(captor.capture(), any());
ReplaceOneModel<Document> updateModel = (ReplaceOneModel<Document>) captor.getValue().get(0);
assertThat(updateModel.getFilter()).isEqualTo(new Document("first_name", "danerys"));
assertThat(updateModel.getReplacement().getString("first_name")).isEqualTo("Minsu");
assertThat(updateModel.getReplacement().getString("lastName")).isEqualTo("Kim");
}
class SomeDomainType {
@Id String id;