在Kotlin SpringBoot中用Criteria对比MongoDB的DateTime字段与指定日期
MongoDB LocalDateTime字段与LocalDate过滤不生效问题修复
问题场景
数据库中dateTimeValidUntil字段存储为LocalDateTime类型(示例值:2022-12-29T23:59:59.999999),用LocalDate类型的refDate(比如2023-01-01)过滤时,无法排除已过期的记录(即dateTimeValidUntil早于refDate的记录),就算把refDate转成当日起始时刻(atStartOfDay())也没用。
当前错误代码
fun find(collegeId: Int, refDate: LocalDate): List<College> { return mongoTemplate.find( Query.query( Criteria.where("college._id").`is`(collegeId) .andOperator( Criteria().orOperator( Criteria.where("dateTimeValidUntil").`is`(null), Criteria.where("dateTimeValidUntil").gte(refDate) ) ) ),College::class.java,"college" )}
问题原因
直接用LocalDate和MongoDB里的LocalDateTime字段比较,类型转换逻辑出了问题。虽然LocalDate会被默认转为当日00:00:00的时间,但MongoTemplate可能没正确识别这种跨类型比较规则,导致gte判断失效,过期记录没被过滤掉。
修复方案
把refDate明确转换成LocalDateTime类型的当日起始时刻,确保查询条件用同类型做比较。修改后的代码如下:
fun find(collegeId: Int, refDate: LocalDate): List<College> { // 明确转为当日00:00:00的LocalDateTime val refStartDateTime = refDate.atStartOfDay() return mongoTemplate.find( Query.query( Criteria.where("college._id").`is`(collegeId) .andOperator( Criteria().orOperator( Criteria.where("dateTimeValidUntil").isNull(), Criteria.where("dateTimeValidUntil").gte(refStartDateTime) ) ) ), College::class.java, "college" ) }
如果还是不行,检查实体类里dateTimeValidUntil字段的类型是否确实是LocalDateTime,或者试试指定时区转换(比如用系统默认时区):
val refStartDateTime = refDate.atStartOfDay(ZoneId.systemDefault())
补充验证
如果需求是排除所有早于refDate当天的记录,也可以反向验证:查询dateTimeValidUntil为null,或者dateTimeValidUntil不小于refDate的起始时刻,逻辑和上面一致,核心就是保证比较的类型统一。
内容的提问来源于stack exchange,提问作者Techie
相关产品推荐
相关产品推荐

