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