如何在Kotlin Exposed中访问min()/max()表达式的返回值?
解决Exposed中聚合函数min/max日期返回类型为Nothing的问题
问题原因
在Exposed中直接使用MetricValues.date.min()或MetricValues.date.max()作为查询字段时,框架无法正确推断聚合结果的类型,导致通过row[xxx]访问时类型被识别为Nothing,进而引发运行时错误。虽然调试能看到数据库返回了正确值,但类型系统无法识别。
解决方案:为聚合字段指定别名
通过给聚合函数的结果添加别名,让Exposed能正确关联字段类型,解决类型推断问题。具体步骤如下:
- 先为
min()和max()的结果定义带别名的表达式 - 在查询中使用这些别名表达式
- 通过别名从结果行中取值
修改后的完整代码:
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
相关产品推荐
相关产品推荐

