Skip to content

MongoDB Adapter

MongoKacheController wraps the official MongoDB Kotlin coroutines driver. Every method receives a MongoCollection<T> and a trailing lambda that executes directly against that collection.

Setup

val cache: CacheClient = RedisCacheClient("redis://localhost:6379")
val controller = MongoKacheController(cache = cache)

val db = MongoClient.create("mongodb://localhost:27017").getDatabase("myApp")
val users: MongoCollection<User> = db.getCollection("users")

Methods

// read one by id
suspend fun <T : Model> get(
    id: String,
    collection: MongoCollection<T>,
    serializer: KSerializer<T>,
    expire: Duration? = null,
    fieldExpire: Duration? = null,
    getData: suspend MongoCollection<T>.() -> T?,
): T?

// read many
suspend fun <T : Model> getAll(
    collection: MongoCollection<T>,
    serializer: KSerializer<T>,
    expire: Duration? = null,
    cacheKey: String = collection.cacheKey(),
    maxCacheSize: Int? = null,
    getData: suspend MongoCollection<T>.() -> List<T>,
): List<T>

// write one
suspend fun <T : Model> set(
    collection: MongoCollection<T>,
    cacheKey: String = collection.cacheKey(),
    serializer: KSerializer<T>,
    expire: Duration? = null,
    fieldExpire: Duration? = null,
    invalidateVolatiles: Boolean = true,
    setData: suspend MongoCollection<T>.() -> T?,
): T?

// write many
suspend fun <T : Model> setAll(
    collection: MongoCollection<T>,
    serializer: KSerializer<T>,
    expire: Duration? = null,
    fieldExpire: Duration? = null,
    invalidateVolatiles: Boolean = true,
    maxCacheSize: Int? = null,
    cacheKey: String = collection.cacheKey(),
    setData: suspend MongoCollection<T>.() -> List<T>?,
): Boolean

// cached volatile query result
suspend fun <T : Model, R : Any> getVolatile(
    fieldName: String,
    collection: MongoCollection<T>,
    serializer: KSerializer<R>,
    setData: suspend MongoCollection<T>.() -> R,
): R

// delete one
suspend fun <T : Model> remove(
    id: String,
    collection: MongoCollection<T>,
    deleteData: suspend MongoCollection<T>.() -> Boolean,
): Boolean

// delete many
suspend fun <T : Model> removeAll(
    collection: MongoCollection<T>,
    cacheKey: String = collection.cacheKey(),
    deleteData: suspend MongoCollection<T>.() -> Boolean,
): Boolean

// fire-and-forget write (requires asyncWriteScope)
suspend fun <T : Model> setAsync(...)
suspend fun <T : Model> setAllAsync(...)

Example

// write-through upsert
val updated = controller.set(users, User.serializer()) {
    findOneAndUpdate(
        Filters.eq("_id", userId),
        Updates.set(User::firstName.name, "NewName"),
        FindOneAndUpdateOptions().returnDocument(ReturnDocument.AFTER),
    )
}

// read-through filtered query (result cached as volatile)
val admins = controller.getAll(
    users, User.serializer(),
    cacheKey = "users:role:admin",
) {
    find(Filters.eq(User::role.name, "admin")).toList()
}

// cached aggregate (count, sum, etc.)
val count = controller.getVolatile(
    "users:count",
    users,
    Long.serializer(),
) {
    countDocuments()
}