Skip to main content

Overview

invirt-mongodb is a thin Kotlin layer on top of the MongoDB Kotlin driver. It provides:

  • A small Mongo wrapper for managing the client lifecycle and running transactions.
  • Document interfaces (VersionedDocument, TimestampedDocument) with optimistic locking and managed timestamps.
  • Strongly-typed filters, sorts and indexes via KProperty extensions.
  • A bridge from Invirt's DataFilter / Sort / Page abstractions to native MongoDB constructs.
  • A cursor-based pagination helper for aggregation pipelines.
  • Helpers for Atlas Search and for running Mongock migrations.

Dependency

implementation(platform("dev.invirt:invirt-bom:${invirtVersion}"))
implementation("dev.invirt:invirt-mongodb")

Connecting

The Mongo class wraps a MongoClient and is the entry point for the rest of the API. The database name is extracted from the connection string — an explicit database name is required.

val mongo = Mongo("mongodb://localhost:27017/myapp")

mongo.database // com.mongodb.kotlin.client.MongoDatabase
mongo.databaseName // "myapp"

mongo.runInTransaction { session ->
// ...
}

mongo.close()

runInTransaction starts a session with WriteConcern.MAJORITY and either commits or aborts based on the block outcome.

Documents

VersionedDocument and TimestampedDocument are interfaces your domain documents can implement to opt into optimistic locking and managed createdAt / updatedAt timestamps.

data class Product(
override val id: String = uuid7(),
val name: String,
val priceMinor: Long,
override var version: Long = 0,
override var createdAt: Instant = mongoNow(),
override var updatedAt: Instant = mongoNow()
) : TimestampedDocument

MongoCollection.insert(document) and MongoCollection.update(document) (and their transactional txInsert / txUpdate counterparts) handle version increment and timestamp maintenance automatically. See Collection operations for the full surface.

Indexes

Indexes can be defined fluently from a string or a KProperty:

collection.createIndices(
Product::name.asc(),
Product::priceMinor.desc(),
Product::name.asc { caseInsensitive() },
*TimestampedDocument.allIndices()
)

TimestampedDocument.allIndices() returns the version + createdAt + updatedAt indices used by the framework's optimistic locking and timestamp handling.

Querying

For ad-hoc queries the standard Kotlin driver API works as-is. For composing filters, sort and pagination together, use MongoQuery:

val results: RecordsPage<Product> = collection.query()
.andFilter(Product::priceMinor.mongoGte(1000_00), Product::name.mongoIn("Apple", "Pear"))
.sort(Product::createdAt.mongoSortDesc())
.page(request.page())
.find()

MongoCollection.pagedQuery(...) exposes the same operation as a single call when you already have the filter/sort/page constructed elsewhere. To translate Invirt's request-derived DataFilter into a MongoDB filter, use .mongoFilter():

"/products" GET { request ->
val filter = productFilter(request)?.mongoFilter() ?: Filters.empty()
val results = collection.pagedQuery(filter, request.page(), request.sort()?.mongoSort()?.let { listOf(it) } ?: emptyList())
// ...
}

What's next

See the API reference for the complete surface: