Repositories

MonkoRepository provides typed CRUD, queries, cursors, and atomic operations.

Defining a repository

class PersonsRepo(driver: MonkoDriver) : MonkoRepository<Person>(
    name = "persons",
    storedType = kType(),
    driver = driver,
)

The repository is a singleton registered in Kontainer. The MonkoDriver is injected as a dynamic (per-request) dependency.

CRUD operations

// Insert with explicit key
val stored = repo.insert("alice-1", Person(name = "Alice", age = 30, email = "alice@example.com"))

// Insert with auto-generated ObjectId
val stored = repo.insert(New(Person(name = "Bob", age = 25, email = "bob@example.com")))

// Find by ID
val person = repo.findById("persons/alice-1")  // returns Stored<Person>?

// Find all
val everyone = repo.findAll()  // returns MonkoCursor<Stored<Person>>

// Save (update)
val modified = person!!.modify { copy(age = 31) }
repo.save(modified)

// Atomic read-modify-write
repo.modifyById("persons/alice-1") { copy(age = it.age + 1) }

// Delete
repo.remove("persons/alice-1")

// Delete all
repo.removeAll()

Custom queries

// Type-safe query with builder
val berliners = repo.find { r ->
    filter(r.address.city.eq("Berlin"))
    filter(r.age.gte(18))
    sort(r.name.asc)
    limit(50)
}

// Access results
berliners.toList()       // List<Stored<Person>>
berliners.count           // number of results returned
berliners.fullCount       // total matching (for pagination)
berliners.forEach { ... } // iterate

Cursors

MonkoCursor<T> wraps query results with metadata:

val cursor = repo.find { r ->
    filter(r.status.eq("active"))
    sort(r.createdAt.desc)
    skip(20)
    limit(10)
}

cursor.count       // 10 (results in this page)
cursor.fullCount   // 253 (total matching documents)
cursor.entries     // List<Stored<Person>>

Batch operations

// Insert multiple
val people = listOf(
    Person("Alice", 30, "alice@example.com"),
    Person("Bob", 25, "bob@example.com"),
    Person("Charlie", 35, "charlie@example.com"),
)

repo.batchInsertValues(people)

Collection stats

val stats = repo.getStats()
// stats.documentCount, stats.indexes, etc.
Repositories are the access layer. Domain logic stays in services. A repository handles persistence — queries, indexes, and hooks. Nothing more.