You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Kotlin Exposed中访问min()/max()表达式的返回值?

解决Exposed中聚合函数min/max日期返回类型为Nothing的问题

问题原因

在Exposed中直接使用MetricValues.date.min()或MetricValues.date.max()作为查询字段时,框架无法正确推断聚合结果的类型,导致通过row[xxx]访问时类型被识别为Nothing,进而引发运行时错误。虽然调试能看到数据库返回了正确值,但类型系统无法识别。

解决方案:为聚合字段指定别名

通过给聚合函数的结果添加别名,让Exposed能正确关联字段类型,解决类型推断问题。具体步骤如下:

  1. 先为min()和max()的结果定义带别名的表达式
  2. 在查询中使用这些别名表达式
  3. 通过别名从结果行中取值

修改后的完整代码:

object MetricValues : Table("metric_values") {
    val id = integer("id").autoIncrement()
    val metricDefinitionId = reference(
        "metric_definition_id",
        MetricDefinitions.id,
        onDelete = ReferenceOption.CASCADE,
        onUpdate = ReferenceOption.CASCADE
    )
    val adId = reference(
        "ad_id",
        Ads.id,
        onDelete = ReferenceOption.CASCADE,
        onUpdate = ReferenceOption.CASCADE
    )
    val date = datetime("date")
    val value = double("value")

    override val primaryKey = PrimaryKey(id)
}

--

val result = newSuspendedTransaction(Dispatchers.IO, client) {
    // 为聚合结果定义别名
    val minDate = MetricValues.date.min().alias("min_date")
    val maxDate = MetricValues.date.max().alias("max_date")

    MetricValues
        .select(MetricValues.adId, minDate, maxDate)
        .where {
            MetricValues.adId inList (adIds.map { UUID.fromString(it) })
        }
        .groupBy(MetricValues.adId)
        .associate { row ->
            // 通过别名取值,类型推断正常
            MetricValues.adId.toString() to getDifferenceInDays(
                row[minDate],
                row[maxDate]
            )
        }
}

补充说明

之前sum()用!!能临时解决,是因为sum()的返回类型本身是可空的(比如无数据时返回null),但min()/max()在分组查询且分组有数据的情况下不会返回null,但其类型推断失败的程度更严重,导致!!无法将Nothing转为有效类型。使用别名是更可靠的解决方案,同时也让代码可读性更强。

内容的提问来源于stack exchange,提问作者fjen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 02:33:18