
com.hexagonkt.store.mongodb.MongoDbStore.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of store_mongodb Show documentation
Show all versions of store_mongodb Show documentation
The atoms of your platform
package com.hexagonkt.store.mongodb
import com.hexagonkt.converters.convert
import com.hexagonkt.core.fail
import com.hexagonkt.core.filterNotEmpty
import com.hexagonkt.core.toLocalDateTime
import com.hexagonkt.store.Store
import com.mongodb.ConnectionString
import com.mongodb.client.FindIterable
import com.mongodb.client.MongoClients
import com.mongodb.client.MongoCollection
import com.mongodb.client.MongoDatabase
import com.mongodb.client.model.Filters
import com.mongodb.client.model.ReplaceOptions
import com.mongodb.client.model.Updates
import org.bson.BsonBinary
import org.bson.BsonString
import org.bson.Document
import org.bson.conversions.Bson
import org.bson.types.Binary
import java.net.URL
import java.nio.ByteBuffer
import java.time.LocalDateTime
import java.time.ZoneId
import java.time.ZoneOffset
import java.util.*
import kotlin.collections.ArrayList
import kotlin.reflect.KClass
import kotlin.reflect.KProperty1
class MongoDbStore(
override val type: KClass,
override val key: KProperty1,
private val database: MongoDatabase,
override val name: String = type.java.simpleName,
private val encoder: (T) -> Map<*, *> = { it.convert(Map::class) },
private val decoder: (Map<*, *>) -> T = { it.convert(type) },
) : Store {
companion object {
fun database(url: String): MongoDatabase = ConnectionString(url).let {
MongoClients.create(it).getDatabase(it.database ?: fail)
}
}
val collection: MongoCollection = this.database.getCollection(name)
constructor(
type: KClass, key: KProperty1, url: String, name: String = type.java.simpleName
) :
this(type, key, database(url), name)
override fun insertOne(instance: T): K {
collection.insertOne(map(instance))
return key.get(instance)
}
override fun insertMany(instances: List): List {
collection.insertMany(instances.map { instance -> map(instance) })
return instances.map { key.get(it) }
}
override fun saveOne(instance: T): K? {
val filter = createKeyFilter(key.get(instance))
val options = ReplaceOptions().upsert(true)
val result = collection.replaceOne(filter, map(instance), options)
val upsertedId = result.upsertedId
@Suppress("UNCHECKED_CAST")
return if (upsertedId == null) null
else fromStore(upsertedId as Any) as K
}
override fun saveMany(instances: List): List =
instances.map(this::saveOne)
override fun replaceOne(instance: T): Boolean {
val document = map(instance)
val filter = createKeyFilter(key.get(instance))
val result = collection.replaceOne(filter, document)
// *NOTE* that 'modifiedCount' returns 0 for matched records with unchanged update values
return result.matchedCount == 1L
}
override fun replaceMany(instances: List): List =
instances.mapNotNull { if (replaceOne(it)) it else null }
override fun updateOne(key: K, updates: Map): Boolean {
require(updates.isNotEmpty())
val filter = createKeyFilter(key)
val update = createUpdate(updates)
val result = collection.updateOne(filter, update)
// *NOTE* that 'modifiedCount' returns 0 for matched records with unchanged update values
return result.matchedCount == 1L
}
override fun updateMany(filter: Map, updates: Map): Long {
require(updates.isNotEmpty())
val updateFilter = createFilter(filter)
val update = createUpdate(updates)
val result = collection.updateMany(updateFilter, update)
// *NOTE* that 'modifiedCount' returns 0 for matched records with unchanged update values
return result.matchedCount
}
override fun deleteOne(id: K): Boolean {
val filter = createKeyFilter(id)
val result = collection.deleteOne(filter)
return result.deletedCount == 1L
}
override fun deleteMany(filter: Map): Long {
val deleteFilter = createFilter(filter)
val result = collection.deleteMany(deleteFilter)
return result.deletedCount
}
override fun findOne(key: K): T? {
val result = collection.find(createKeyFilter(key)).first()?.filterNotEmpty()
return if (result == null) null else fromStore(result as Map)
}
override fun findOne(key: K, fields: List): Map? {
val filter = createKeyFilter(key)
val result = collection
.find(filter)
.projection(createProjection(fields))
.first()?.filterNotEmpty()
return result?.mapValues { fromStore(it.value) }
}
override fun findMany(
filter: Map,
limit: Int?,
skip: Int?,
sort: Map
): List {
val findFilter = createFilter(filter)
val findSort = createSort(sort)
val query = collection.find(findFilter).sort(findSort)
pageQuery(limit, query, skip)
val result = query.into(ArrayList())
return result.map { fromStore(it.filterNotEmpty()) }
}
override fun findMany(
filter: Map,
fields: List,
limit: Int?,
skip: Int?,
sort: Map
): List
© 2015 - 2025 Weber Informatics LLC | Privacy Policy