iT邦幫忙

2023 iThome 鐵人賽

DAY 13
0

前情提要

今天我們要將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) }
}

Repo

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)
        }
}

Get All

取得全部是比較簡單的XD
只要將collection取得後,就可以使用find(),就能拿出collection下的所有資料囉

Add one

這邊我們將collection存成document,這樣我們只要將要存入的資料轉成document,就可以順利儲存進去囉。

Update one

這邊有點讓我苦惱😅,無法使用document的行式儲存進去,最後參考這篇文章儲存成功,耗了好多的功夫才完成,將query以及要存的資料轉換成Bson最後才成功。
https://www.mongodb.com/docs/drivers/kotlin/coroutine/current/usage-examples/updateOne/

Delete one

這邊類似Update的作法,將query寫出來後,就可以囉

總結

今天我們將MongoDB給串接上去了! 灑花,這樣就可以繼續往前進囉,有了這些基本功能後,我們要怎麼確保我們的結果對不對呢? 就可以依靠測試來進行了,但一堆手動測試超浪費生命,一定要自動化才行啦。

參考資料

Getting Started with Backend Development in Kotlin Using Spring Boot 3 & MongoDB


上一篇
[小城鎮] 實際儲存資料 - Mongodb
下一篇
[小城鎮] 笨蛋,測試,召喚獸 - 自動化測試是甚麼?
系列文
Kotlin魔法:Spring Boot 3的fp奇幻冒險30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
Brandy
iT邦新手 2 級 ‧ 2023-09-28 06:22:59

為什麼 getAll 不是 suspend fun

linitachi iT邦新手 4 級 ‧ 2023-09-28 21:14:58 檢舉

com.mongodb.kotlin.client.coroutine
的collection.find(),竟然不是suspend funciton
/images/emoticon/emoticon04.gif

我要留言

立即登入留言