diff --git a/mongodb/aggregation/pom.xml b/mongodb/aggregation/pom.xml
index 7f45c01b0..c585a0651 100644
--- a/mongodb/aggregation/pom.xml
+++ b/mongodb/aggregation/pom.xml
@@ -12,4 +12,18 @@
2.0.0.BUILD-SNAPSHOT
-
\ No newline at end of file
+
+
+ org.testcontainers
+ mongodb
+ 1.15.0-rc1
+ test
+
+
+ org.testcontainers
+ junit-jupiter
+ 1.15.0-rc1
+ test
+
+
+
diff --git a/mongodb/aggregation/src/main/java/example/springdata/mongodb/aggregationupdate/Score.java b/mongodb/aggregation/src/main/java/example/springdata/mongodb/aggregationupdate/Score.java
new file mode 100644
index 000000000..b7ec408da
--- /dev/null
+++ b/mongodb/aggregation/src/main/java/example/springdata/mongodb/aggregationupdate/Score.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2020 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package example.springdata.mongodb.aggregationupdate;
+
+import java.util.List;
+
+import org.springframework.data.mongodb.core.mapping.Document;
+
+/**
+ * @author Christoph Strobl
+ */
+@Document("scores")
+class Score {
+
+ private final Integer id;
+ private final String student;
+ private final List homework;
+ private final List quiz;
+ private final Integer extraCredit;
+
+ Score(Integer id, String student, List homework, List quiz, Integer extraCredit) {
+
+ this.id = id;
+ this.student = student;
+ this.homework = homework;
+ this.quiz = quiz;
+ this.extraCredit = extraCredit;
+ }
+}
diff --git a/mongodb/aggregation/src/main/java/example/springdata/mongodb/aggregationupdate/ScoreRepository.java b/mongodb/aggregation/src/main/java/example/springdata/mongodb/aggregationupdate/ScoreRepository.java
new file mode 100644
index 000000000..62fb100eb
--- /dev/null
+++ b/mongodb/aggregation/src/main/java/example/springdata/mongodb/aggregationupdate/ScoreRepository.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2020. the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package example.springdata.mongodb.aggregationupdate;
+
+import org.springframework.data.repository.CrudRepository;
+
+/**
+ * @author Christoph Strobl
+ */
+interface ScoreRepository extends CrudRepository, ScoreRepositoryCustom {
+
+}
diff --git a/mongodb/aggregation/src/main/java/example/springdata/mongodb/aggregationupdate/ScoreRepositoryCustom.java b/mongodb/aggregation/src/main/java/example/springdata/mongodb/aggregationupdate/ScoreRepositoryCustom.java
new file mode 100644
index 000000000..ff90d6db0
--- /dev/null
+++ b/mongodb/aggregation/src/main/java/example/springdata/mongodb/aggregationupdate/ScoreRepositoryCustom.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2020. the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package example.springdata.mongodb.aggregationupdate;
+
+/**
+ * @author Christoph Strobl
+ */
+public interface ScoreRepositoryCustom {
+
+ void calculateTotalScore();
+
+}
diff --git a/mongodb/aggregation/src/main/java/example/springdata/mongodb/aggregationupdate/ScoreRepositoryCustomImpl.java b/mongodb/aggregation/src/main/java/example/springdata/mongodb/aggregationupdate/ScoreRepositoryCustomImpl.java
new file mode 100644
index 000000000..6aae676eb
--- /dev/null
+++ b/mongodb/aggregation/src/main/java/example/springdata/mongodb/aggregationupdate/ScoreRepositoryCustomImpl.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2020 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package example.springdata.mongodb.aggregationupdate;
+
+import org.springframework.data.mongodb.core.MongoOperations;
+import org.springframework.data.mongodb.core.aggregation.AggregationUpdate;
+import org.springframework.data.mongodb.core.aggregation.ArithmeticOperators;
+import org.springframework.data.mongodb.core.aggregation.SetOperation;
+import org.springframework.stereotype.Component;
+
+/**
+ * @author Christoph Strobl
+ */
+@Component
+class ScoreRepositoryCustomImpl implements ScoreRepositoryCustom {
+
+ private final MongoOperations mongoOperations;
+
+ ScoreRepositoryCustomImpl(MongoOperations mongoOperations) {
+ this.mongoOperations = mongoOperations;
+ }
+
+ @Override
+ public void calculateTotalScore() {
+
+ AggregationUpdate update = AggregationUpdate.update().set(SetOperation.builder() //
+ .set("totalHomework").toValueOf(ArithmeticOperators.valueOf("homework").sum()).and() //
+ .set("totalQuiz").toValueOf(ArithmeticOperators.valueOf("quiz").sum())) //
+ .set(SetOperation.builder() //
+ .set("totalScore")
+ .toValueOf(ArithmeticOperators.valueOf("totalHomework").add("totalQuiz").add("extraCredit")));
+
+ mongoOperations.update(Score.class).apply(update).all();
+ }
+}
diff --git a/mongodb/aggregation/src/test/java/example/springdata/mongodb/aggregationupdate/ScoreRepositoryTests.java b/mongodb/aggregation/src/test/java/example/springdata/mongodb/aggregationupdate/ScoreRepositoryTests.java
new file mode 100644
index 000000000..74b8dd863
--- /dev/null
+++ b/mongodb/aggregation/src/test/java/example/springdata/mongodb/aggregationupdate/ScoreRepositoryTests.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2020 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package example.springdata.mongodb.aggregationupdate;
+
+import static org.assertj.core.api.Assertions.*;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+
+import org.bson.Document;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.data.mongodb.config.AbstractMongoClientConfiguration;
+import org.springframework.data.mongodb.core.MongoOperations;
+import org.springframework.data.mongodb.repository.config.EnableMongoRepositories;
+import org.springframework.test.context.junit.jupiter.SpringExtension;
+import org.testcontainers.containers.MongoDBContainer;
+import org.testcontainers.junit.jupiter.Container;
+import org.testcontainers.junit.jupiter.Testcontainers;
+import org.testcontainers.utility.DockerImageName;
+
+import com.mongodb.ConnectionString;
+import com.mongodb.MongoClientSettings.Builder;
+import com.mongodb.client.MongoCollection;
+
+/**
+ * @author Christoph Strobl
+ * @since 2020/08
+ */
+@ExtendWith(SpringExtension.class)
+@Testcontainers
+class ScoreRepositoryTests {
+
+ @Container private static final MongoDBContainer MONGO_DB_CONTAINER = new MongoDBContainer(
+ DockerImageName.parse("mongo:4.2.8"));
+
+ @Autowired MongoOperations operations;
+ @Autowired ScoreRepository repository;
+
+ @Configuration
+ @EnableMongoRepositories
+ static class Config extends AbstractMongoClientConfiguration {
+
+ @Override
+ protected String getDatabaseName() {
+ return "test";
+ }
+
+ @Override
+ protected void configureClientSettings(Builder builder) {
+ builder.applyConnectionString(new ConnectionString(MONGO_DB_CONTAINER.getReplicaSetUrl()));
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ @BeforeEach
+ void beforeEach() throws Exception {
+
+ repository.deleteAll();
+
+ Score score1 = new Score(1, "Maya", Arrays.asList(10, 5, 10), Arrays.asList(10, 8), 0);
+ Score score2 = new Score(2, "Ryan", Arrays.asList(5, 6, 5), Arrays.asList(8, 8), 8);
+
+ repository.saveAll(Arrays.asList(score1, score2));
+ }
+
+ @Test
+ void testAggregationUpdate() {
+
+ repository.calculateTotalScore();
+
+ assertThat(nativeConnection(Score.class).find(new org.bson.Document()).into(new ArrayList<>()))
+ .containsExactlyInAnyOrder( //
+ org.bson.Document.parse(
+ "{\"_id\" : 1, \"student\" : \"Maya\", \"homework\" : [ 10, 5, 10 ], \"quiz\" : [ 10, 8 ], \"extraCredit\" : 0, \"totalHomework\" : 25, \"totalQuiz\" : 18, \"totalScore\" : 43, \"_class\" : \"example.springdata.mongodb.aggregationupdate.Score\"}"),
+ org.bson.Document.parse(
+ "{ \"_id\" : 2, \"student\" : \"Ryan\", \"homework\" : [ 5, 6, 5 ], \"quiz\" : [ 8, 8 ], \"extraCredit\" : 8, \"totalHomework\" : 16, \"totalQuiz\" : 16, \"totalScore\" : 40, \"_class\" : \"example.springdata.mongodb.aggregationupdate.Score\"}"));
+ }
+
+ private MongoCollection nativeConnection(Class> type) {
+ return operations.getCollection(operations.getCollectionName(type));
+ }
+}