Skip to content

Commit 37ff3c6

Browse files
#578 - Add MongoDB example for updates using an Aggregation.
Using testcontainers due to the lack of MongoDB 4.2+ support in flapdoodle.oss
1 parent 174aafb commit 37ff3c6

File tree

6 files changed

+254
-1
lines changed

6 files changed

+254
-1
lines changed

mongodb/aggregation/pom.xml

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,18 @@
1212
<version>2.0.0.BUILD-SNAPSHOT</version>
1313
</parent>
1414

15-
</project>
15+
<dependencies>
16+
<dependency>
17+
<groupId>org.testcontainers</groupId>
18+
<artifactId>mongodb</artifactId>
19+
<version>1.15.0-rc1</version>
20+
<scope>test</scope>
21+
</dependency>
22+
<dependency>
23+
<groupId>org.testcontainers</groupId>
24+
<artifactId>junit-jupiter</artifactId>
25+
<version>1.15.0-rc1</version>
26+
<scope>test</scope>
27+
</dependency>
28+
</dependencies>
29+
</project>
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/*
2+
* Copyright 2020 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package example.springdata.mongodb.aggregationupdate;
17+
18+
import java.util.List;
19+
20+
import org.springframework.data.mongodb.core.mapping.Document;
21+
22+
/**
23+
* @author Christoph Strobl
24+
*/
25+
@Document("scores")
26+
class Score {
27+
28+
private final Integer id;
29+
private final String student;
30+
private final List<Integer> homework;
31+
private final List<Integer> quiz;
32+
private final Integer extraCredit;
33+
34+
Score(Integer id, String student, List<Integer> homework, List<Integer> quiz, Integer extraCredit) {
35+
36+
this.id = id;
37+
this.student = student;
38+
this.homework = homework;
39+
this.quiz = quiz;
40+
this.extraCredit = extraCredit;
41+
}
42+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/*
2+
* Copyright 2020. the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package example.springdata.mongodb.aggregationupdate;
17+
18+
import org.springframework.data.repository.CrudRepository;
19+
20+
/**
21+
* @author Christoph Strobl
22+
*/
23+
interface ScoreRepository extends CrudRepository<Score, Integer>, ScoreRepositoryCustom {
24+
25+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/*
2+
* Copyright 2020. the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package example.springdata.mongodb.aggregationupdate;
17+
18+
/**
19+
* @author Christoph Strobl
20+
*/
21+
public interface ScoreRepositoryCustom {
22+
23+
void calculateTotalScore();
24+
25+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/*
2+
* Copyright 2020 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package example.springdata.mongodb.aggregationupdate;
17+
18+
import org.springframework.data.mongodb.core.MongoOperations;
19+
import org.springframework.data.mongodb.core.aggregation.AggregationUpdate;
20+
import org.springframework.data.mongodb.core.aggregation.ArithmeticOperators;
21+
import org.springframework.data.mongodb.core.aggregation.SetOperation;
22+
import org.springframework.stereotype.Component;
23+
24+
/**
25+
* @author Christoph Strobl
26+
*/
27+
@Component
28+
class ScoreRepositoryCustomImpl implements ScoreRepositoryCustom {
29+
30+
private final MongoOperations mongoOperations;
31+
32+
ScoreRepositoryCustomImpl(MongoOperations mongoOperations) {
33+
this.mongoOperations = mongoOperations;
34+
}
35+
36+
@Override
37+
public void calculateTotalScore() {
38+
39+
AggregationUpdate update = AggregationUpdate.update().set(SetOperation.builder() //
40+
.set("totalHomework").toValueOf(ArithmeticOperators.valueOf("homework").sum()).and() //
41+
.set("totalQuiz").toValueOf(ArithmeticOperators.valueOf("quiz").sum())) //
42+
.set(SetOperation.builder() //
43+
.set("totalScore")
44+
.toValueOf(ArithmeticOperators.valueOf("totalHomework").add("totalQuiz").add("extraCredit")));
45+
46+
mongoOperations.update(Score.class).apply(update).all();
47+
}
48+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
/*
2+
* Copyright 2020 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package example.springdata.mongodb.aggregationupdate;
17+
18+
import static org.assertj.core.api.Assertions.*;
19+
20+
import java.util.ArrayList;
21+
import java.util.Arrays;
22+
23+
import org.bson.Document;
24+
import org.junit.jupiter.api.BeforeEach;
25+
import org.junit.jupiter.api.Test;
26+
import org.junit.jupiter.api.extension.ExtendWith;
27+
import org.springframework.beans.factory.annotation.Autowired;
28+
import org.springframework.context.annotation.Configuration;
29+
import org.springframework.data.mongodb.config.AbstractMongoClientConfiguration;
30+
import org.springframework.data.mongodb.core.MongoOperations;
31+
import org.springframework.data.mongodb.repository.config.EnableMongoRepositories;
32+
import org.springframework.test.context.junit.jupiter.SpringExtension;
33+
import org.testcontainers.containers.MongoDBContainer;
34+
import org.testcontainers.junit.jupiter.Container;
35+
import org.testcontainers.junit.jupiter.Testcontainers;
36+
import org.testcontainers.utility.DockerImageName;
37+
38+
import com.mongodb.ConnectionString;
39+
import com.mongodb.MongoClientSettings.Builder;
40+
import com.mongodb.client.MongoCollection;
41+
42+
/**
43+
* @author Christoph Strobl
44+
* @since 2020/08
45+
*/
46+
@ExtendWith(SpringExtension.class)
47+
@Testcontainers
48+
class ScoreRepositoryTests {
49+
50+
@Container private static final MongoDBContainer MONGO_DB_CONTAINER = new MongoDBContainer(
51+
DockerImageName.parse("mongo:4.2.8"));
52+
53+
@Autowired MongoOperations operations;
54+
@Autowired ScoreRepository repository;
55+
56+
@Configuration
57+
@EnableMongoRepositories
58+
static class Config extends AbstractMongoClientConfiguration {
59+
60+
@Override
61+
protected String getDatabaseName() {
62+
return "test";
63+
}
64+
65+
@Override
66+
protected void configureClientSettings(Builder builder) {
67+
builder.applyConnectionString(new ConnectionString(MONGO_DB_CONTAINER.getReplicaSetUrl()));
68+
}
69+
}
70+
71+
@SuppressWarnings("unchecked")
72+
@BeforeEach
73+
void beforeEach() throws Exception {
74+
75+
repository.deleteAll();
76+
77+
Score score1 = new Score(1, "Maya", Arrays.asList(10, 5, 10), Arrays.asList(10, 8), 0);
78+
Score score2 = new Score(2, "Ryan", Arrays.asList(5, 6, 5), Arrays.asList(8, 8), 8);
79+
80+
repository.saveAll(Arrays.asList(score1, score2));
81+
}
82+
83+
@Test
84+
void testAggregationUpdate() {
85+
86+
repository.calculateTotalScore();
87+
88+
assertThat(nativeConnection(Score.class).find(new org.bson.Document()).into(new ArrayList<>()))
89+
.containsExactlyInAnyOrder( //
90+
org.bson.Document.parse(
91+
"{\"_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\"}"),
92+
org.bson.Document.parse(
93+
"{ \"_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\"}"));
94+
}
95+
96+
private MongoCollection<Document> nativeConnection(Class<?> type) {
97+
return operations.getCollection(operations.getCollectionName(type));
98+
}
99+
}

0 commit comments

Comments
 (0)