All Downloads are FREE. Search and download functionalities are using the official Maven repository.

invirt.data.mongodb.index.kt Maven / Gradle / Ivy

There is a newer version: 0.10.11
Show newest version
package invirt.data.mongodb

import com.mongodb.client.model.Indexes
import com.mongodb.kotlin.client.MongoCollection
import org.slf4j.LoggerFactory
import kotlin.reflect.KClass
import kotlin.reflect.full.findAnnotation
import kotlin.reflect.full.isSubclassOf
import kotlin.reflect.full.memberProperties

@Target(AnnotationTarget.PROPERTY)
@Retention(AnnotationRetention.RUNTIME)
@MustBeDocumented
annotation class Indexed(
    val order: Order = Order.ASC,
    vararg val fields: String
) {

    enum class Order {
        ASC,
        DESC
    }
}

@Target(AnnotationTarget.PROPERTY)
@Retention(AnnotationRetention.RUNTIME)
@MustBeDocumented
annotation class TextIndexed(
    vararg val fields: String
)

fun  MongoCollection.createIndexes() {
    createPropertyIndexes(this.documentClass.kotlin)

    // Handling Timestamped explicitly, because annotations are not inherited in Kotlin
    // so we cannot simply add @Indexed on Timestamped.createdAt
    if (this.documentClass.kotlin.isSubclassOf(TimestampedEntity::class)) {
        createPropertyIndexes(TimestampedEntity::class)
    }
}

private fun MongoCollection<*>.createPropertyIndexes(cls: KClass<*>) {
    val log = LoggerFactory.getLogger("invirt.data.mongodb")
    val textIndexedFields = mutableListOf()
    cls.memberProperties.forEach { property ->

        // Indexed properties
        property.findAnnotation()?.let { annotation ->
            val fields = if (annotation.fields.isEmpty()) listOf(property.name) else annotation.fields.toList()
            fields.forEach { field ->
                val index = when (annotation.order) {
                    Indexed.Order.ASC -> Indexes.ascending(field)
                    Indexed.Order.DESC -> Indexes.descending(field)
                }
                createIndex(index)
                log.info("Creating ${annotation.order} index for ${cls.simpleName}.${field}")
            }
        }

        // Text indexed properties need collecting into one index as Mongo only supports one text index
        property.findAnnotation()?.let { annotation ->
            val fields = if (annotation.fields.isEmpty()) listOf(property.name) else annotation.fields.toList()
            textIndexedFields.addAll(fields)
        }
    }

    if (textIndexedFields.isNotEmpty()) {
        createIndex(Indexes.compoundIndex(textIndexedFields.map { Indexes.text(it) }))
        log.info("Creating text index for ${textIndexedFields.joinToString(", ") { cls.simpleName + "." + it }}")
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy