今天我們要將MongoDB給串上我們的專案! 有了DB以後,我們關閉程式就不會遇到資料不見的問題了,並且外來也可以水平擴充之類的,增加我們資料的安全性。
首先我們要將mongo DB給連線建立起來。
這邊我們偷懶一點,將連線寫死在code之中,理想上要把它抽成環境變數!這樣才可以對測試環境、開發環境、正式環境做控制。
package utils.config
import arrow.core.Either
import com.mongodb.kotlin.client.coroutine.MongoClient
import com.mongodb.kotlin.client.coroutine.MongoDatabase
import model.MyError
object MongodbConfig {
private const val ConnectionString =
"mongodb://localhost:27017"
private val client = MongoClient.create(connectionString = ConnectionString)
fun setupMongoConnection(): Either<MyError, MongoDatabase> =
Either.catch {
client.getDatabase(databaseName = "Ironman")
}.mapLeft { MyError.MongoConnectError(it) }
}
package Repo
import arrow.core.Either
import arrow.core.flatMap
import com.mongodb.client.model.Filters
import com.mongodb.client.model.Updates
import com.mongodb.kotlin.client.coroutine.MongoDatabase
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
import model.ContactInfo
import model.Customer
import model.MyError
import model.Name
import org.bson.Document
import utils.config.MongodbConfig.setupMongoConnection
import utils.decodeFromStringEither
object CustomerRepo {
private val customerList = mutableListOf<Customer>()
private val db: Either<MyError, MongoDatabase> = setupMongoConnection()
fun getCustomer(): Either<MyError, List<Customer>> =
db.map {
it.getCollection<Document>(collectionName = "customers")
}.map { collection ->
collection.find()
}.flatMap {
Json.decodeFromStringEither<List<Customer>>(it.toString())
}.mapLeft {
MyError.CustomerNotFoundError(customerId = "all")
}
suspend fun addCustomer(customer: Customer): Either<MyError, Customer> =
db.map {
it.getCollection<Document>(collectionName = "customers")
}.map { collection ->
val json = Json.encodeToString(customer)
val document = Document.parse(json)
collection.insertOne(document)
}.map {
customer
}
suspend fun updateCustomer(name: Name, customer: Customer) =
db.map {
it.getCollection<Document>(collectionName = "customers")
}.map { collection ->
val query = Filters.eq(Customer::name.name, name.value)
val updates = Updates.combine(
Updates.set(Customer::name.name, customer.name.value),
Updates.set(Customer::age.name, customer.age.value),
Updates.set(Customer::contactInfo.name, ContactInfo.toString(customer.contactInfo)),
)
collection.updateOne(query, updates)
}
suspend fun deleteCustomer(name: Name) =
db.map {
it.getCollection<Document>(collectionName = "customers")
}.map { collection ->
val query = Filters.eq(Customer::name.name, name.value)
collection.deleteOne(query)
}
}
取得全部是比較簡單的XD
只要將collection取得後,就可以使用find(),就能拿出collection下的所有資料囉
這邊我們將collection存成document,這樣我們只要將要存入的資料轉成document,就可以順利儲存進去囉。
這邊有點讓我苦惱😅,無法使用document的行式儲存進去,最後參考這篇文章儲存成功,耗了好多的功夫才完成,將query以及要存的資料轉換成Bson最後才成功。
https://www.mongodb.com/docs/drivers/kotlin/coroutine/current/usage-examples/updateOne/
這邊類似Update的作法,將query寫出來後,就可以囉
今天我們將MongoDB給串接上去了! 灑花,這樣就可以繼續往前進囉,有了這些基本功能後,我們要怎麼確保我們的結果對不對呢? 就可以依靠測試來進行了,但一堆手動測試超浪費生命,一定要自動化才行啦。
Getting Started with Backend Development in Kotlin Using Spring Boot 3 & MongoDB
為什麼 getAll 不是 suspend fun
com.mongodb.kotlin.client.coroutine
的collection.find(),竟然不是suspend funciton