Getting Started
From dependency to your first typed query in six steps.
1. Add the dependencies
// build.gradle.kts
plugins {
kotlin("jvm")
id("com.google.devtools.ksp")
}
dependencies {
implementation("io.peekandpoke.ultra:monko:0.107.2")
ksp("io.peekandpoke.ultra:monko:0.107.2") // KSP processor for type-safe property paths
} 2. Define an entity
Annotate your data class with @Vault. KSP generates type-safe property accessors at compile time.
import io.peekandpoke.ultra.vault.Vault
@Vault
data class Person(
val name: String,
val age: Int,
val email: String,
val address: Address = Address(),
)
@Vault
data class Address(
val city: String = "",
val zip: String = "",
) 3. Create a repository
import io.peekandpoke.monko.MonkoRepository
import io.peekandpoke.monko.MonkoDriver
class PersonsRepo(driver: MonkoDriver) : MonkoRepository<Person>(
name = "persons",
storedType = kType(),
driver = driver,
) 4. Configure the connection
import io.peekandpoke.monko.MongoDbConfig
val config = MongoDbConfig(
connectionString = "mongodb://root:root@localhost:27017",
database = "my_app",
) 5. Basic CRUD
// Insert
val stored = repo.insert("person-1", Person(name = "Alice", age = 30, email = "alice@example.com"))
// stored._id -> "persons/person-1"
// stored._key -> "person-1"
// stored() -> Person(name="Alice", ...)
// Find by ID
val found = repo.findById("persons/person-1")
// Update
val updated = found!!.modify { copy(age = 31) }
repo.save(updated)
// Atomic read-modify-write
repo.modifyById("persons/person-1") { copy(age = it.age + 1) }
// Delete
repo.remove("persons/person-1")
// Find all
val everyone = repo.findAll() 6. Your first typed query
val adults = repo.find { r ->
filter(r.age.gte(18))
sort(r.name.asc)
limit(20)
} The r.age and r.name accessors are generated by KSP from
the Person data class. Rename a field and the query breaks at compile time,
not at runtime.
That's it. Entity, repository, config, query. Everything else builds on these foundations.