1+ import com.mongodb.client.model.Aggregates.group
2+ import com.mongodb.client.model.Aggregates.limit
3+ import com.mongodb.client.model.Aggregates.sort
4+ import com.mongodb.kotlin.client.coroutine.MongoClient
5+ import config.getConfig
6+ import kotlinx.coroutines.flow.firstOrNull
7+ import kotlinx.coroutines.runBlocking
8+ import org.junit.jupiter.api.AfterAll
9+ import org.junit.jupiter.api.AfterEach
10+ import org.junit.jupiter.api.Assertions
11+ import org.junit.jupiter.api.Test
12+ import org.junit.jupiter.api.TestInstance
13+
14+ import com.mongodb.kotlin.client.model.Filters.eq
15+ import com.mongodb.kotlin.client.model.Filters.all
16+ import com.mongodb.kotlin.client.model.Indexes
17+ import com.mongodb.kotlin.client.model.Projections.excludeId
18+ import com.mongodb.kotlin.client.model.Projections.fields
19+ import com.mongodb.kotlin.client.model.Projections.include
20+ import com.mongodb.client.model.Sorts.orderBy
21+ import com.mongodb.kotlin.client.model.Accumulators.avg
22+ import com.mongodb.kotlin.client.model.Sorts
23+
24+ import com.mongodb.kotlin.client.model.Filters.gte
25+ import com.mongodb.kotlin.client.model.Updates.addToSet
26+ import com.mongodb.kotlin.client.model.Updates.combine
27+ import com.mongodb.kotlin.client.model.Updates.max
28+ import kotlin.test.assertEquals
29+ import kotlin.test.assertTrue
30+
31+ @TestInstance(TestInstance .Lifecycle .PER_CLASS )
32+ internal class BuildersDataClassTest {
33+
34+ companion object {
35+ val config = getConfig()
36+ val client = MongoClient .create(config.connectionUri)
37+ val database = client.getDatabase(" school" )
38+
39+ @AfterAll
40+ @JvmStatic
41+ fun afterAll () {
42+ runBlocking {
43+ client.close()
44+ }
45+ }
46+ }
47+
48+ @AfterEach
49+ fun afterEach () {
50+ runBlocking {
51+ database.drop()
52+ }
53+ }
54+
55+ // :snippet-start: data-class
56+ data class Student (
57+ val name : String ,
58+ val teachers : List <String >,
59+ val gradeAverage : Double
60+ )
61+ // :snippet-end:
62+
63+
64+ @Test
65+ fun filtersTest () = runBlocking {
66+
67+ val collection = database.getCollection<Student >(" students" )
68+
69+ // :snippet-start: filters-data-class
70+ val student = Student (
71+ " Sandra Nook" ,
72+ listOf (" Alvarez" , " Gruber" ),
73+ 85.7
74+ )
75+
76+ // Equivalent equality queries
77+ Student ::name.eq(student.name)
78+ eq(Student ::name, student.name)
79+ Student ::name eq student.name // Infix notation
80+
81+ // Equivalent array queries
82+ all(Student ::teachers, student.teachers)
83+ Student ::teachers.all(student.teachers)
84+ Student ::teachers all student.teachers // Infix notation
85+ // :snippet-end:
86+
87+ collection.insertOne(student)
88+ val filter = eq(Student ::name, student.name)
89+ val result = collection.find(filter).firstOrNull()
90+ Assertions .assertEquals(student, result)
91+ }
92+
93+ @Test
94+ fun indexesTest () = runBlocking {
95+
96+ val collection = database.getCollection<Student >(" students" )
97+
98+ // :snippet-start: indexes-data-class
99+ val ascendingIdx = Indexes .ascending(Student ::name)
100+ val descendingIdx = Indexes .descending(Student ::teachers)
101+
102+ val ascIdxName = collection.createIndex(ascendingIdx)
103+ val descIdxName = collection.createIndex(descendingIdx)
104+ // :snippet-end:
105+
106+ assertEquals(" name_1" , ascIdxName)
107+ }
108+
109+ @Test
110+ fun projectionsTest () = runBlocking {
111+
112+ val collection = database.getCollection<Student >(" students" )
113+
114+ val student = Student (
115+ " Sandra Nook" ,
116+ listOf (" Alvarez" , " Gruber" ),
117+ 85.7
118+ )
119+ collection.insertOne(student)
120+
121+ // :snippet-start: projections-data-class
122+ val combinedProj = fields(
123+ include(Student ::name, Student ::gradeAverage),
124+ excludeId()
125+ )
126+
127+ collection.find().projection(combinedProj)
128+ // :snippet-end:
129+
130+ data class Result (val name : String , val gradeAverage : Double )
131+ val result = collection.find<Result >().projection(combinedProj).firstOrNull()
132+
133+ if (result != null ) {
134+ assertEquals(85.7 , result.gradeAverage)
135+ }
136+ }
137+
138+ @Test
139+ fun sortsTest () = runBlocking {
140+
141+ val collection = database.getCollection<Student >(" students" )
142+
143+ val student1 = Student (
144+ " Sandra Nook" ,
145+ listOf (" Alvarez" , " Gruber" ),
146+ 85.7
147+ )
148+ val student2 = Student (
149+ " Paolo Sanchez" ,
150+ listOf (" Gruber" , " Piselli" ),
151+ 89.3
152+ )
153+ collection.insertMany(listOf (student1, student2))
154+
155+ // :snippet-start: sorts-data-class
156+ val sort = orderBy(
157+ Sorts .descending(Student ::gradeAverage),
158+ Sorts .ascending(Student ::name)
159+ )
160+
161+ collection.find().sort(sort)
162+ // :snippet-end:
163+
164+ val result = collection.find().sort(sort).firstOrNull()
165+
166+ if (result != null ) {
167+ assertEquals(89.3 , result.gradeAverage)
168+ }
169+ }
170+
171+ @Test
172+ fun updatesTest () = runBlocking {
173+
174+ val collection = database.getCollection<Student >(" students" )
175+
176+ val students = listOf (
177+ Student (" Sandra Nook" , listOf (" Alvarez" , " Gruber" ),85.7 ),
178+ Student (" Paolo Sanchez" , listOf (" Gruber" , " Piselli" ),89.3 )
179+ )
180+ collection.insertMany(students)
181+
182+ // :snippet-start: updates-data-class
183+ val filter = Student ::gradeAverage gte 85.0
184+ val update = combine(
185+ addToSet(Student ::teachers, " Soto" ),
186+ Student ::gradeAverage.max(90.0 )
187+ )
188+ collection.updateMany(filter, update)
189+ // :snippet-end:
190+
191+ val result = collection.find().firstOrNull()
192+
193+ if (result != null ) {
194+ assertTrue(" Soto" in result.teachers)
195+ assertEquals(result.gradeAverage, 90.0 )
196+ }
197+ }
198+
199+ @Test
200+ fun aggregatesTest () = runBlocking {
201+
202+ val collection = database.getCollection<Student >(" students" )
203+
204+ val students = listOf (
205+ Student (" Sandra Nook" , listOf (" Alvarez" , " Gruber" ),85.7 ),
206+ Student (" Paolo Sanchez" , listOf (" Gruber" , " Piselli" ),89.3 ),
207+ Student (" Katerina Jakobsen" , listOf (" Alvarez" , " Ender" ),97.3 ),
208+ Student (" Emma Frank" , listOf (" Piselli" , " Harbour" ),93.4 ),
209+ Student (" Qasim Haq" , listOf (" Gruber" , " Harbour" ),80.6 )
210+ )
211+ collection.insertMany(students)
212+
213+ // :snippet-start: aggregates-data-class
214+ // Data class to store aggregation result
215+ data class Summary ( val average : Double )
216+
217+ val pipeline = listOf (
218+ // Sorts grades from high to low
219+ sort(Sorts .descending(Student ::gradeAverage)),
220+ // Selects the top 3 students
221+ limit(3 ),
222+ // Calculates the average of their grades and stores value in a Summary instance
223+ group(null , avg(Summary ::average, " \$ ${Student ::gradeAverage.name} " ))
224+ )
225+
226+ val result = collection.aggregate<Summary >(pipeline)
227+ // :snippet-end:
228+
229+ val r = result.firstOrNull()
230+ if (r != null ) {
231+ assertEquals(93.33333333333333 , r.average)
232+ }
233+ }
234+ }
0 commit comments