Scala Mongo驱动2.1.0:Find过滤器生成Long型日期的查询问题
解决Mongo Shell中日期过滤器转为长整型的查询异常问题
我来帮你搞定这个查询异常的问题~首先得理清原因:你在Mongo Shell里使用ISODate()构造日期时,如果传入的字符串格式不完整(比如你写的"2018-04..."),Shell没法正确解析成ISODate对象,反而会把它转成长整型时间戳,导致查询无法匹配文档里的ISODate类型字段。结合你用的是mongo-scala-driver 2.1.0,我分Shell端和Scala代码端两种场景给你解决方案:
1. 修复Mongo Shell中的查询写法
确保ISODate的格式完全标准
Mongo Shell的ISODate()只认完整的ISO 8601格式字符串,比如"2018-04-30T23:59:59.999Z"。把你的查询补全格式后,就能正确识别为日期类型了:
db.getCollection('wwactivities').find({ userId: "2c48bc64-76cd-41b0-88af-b8dfea667960", "activity.completedAt": { $lte: ISODate("2018-04-30T23:59:59.999Z") } })
换用new Date()构造日期对象
如果ISODate()还是出现解析问题,直接用new Date()替代也能解决,Shell会自动识别为日期类型:
db.getCollection('wwactivities').find({ userId: "2c48bc64-76cd-41b0-88af-b8dfea667960", "activity.completedAt": { $lte: new Date("2018-04-30T23:59:59.999Z") } })
要是你已经有目标日期的时间戳(长整型),也可以直接传进去:
// 2018-04-30T23:59:59.999Z对应的时间戳是1525103999999 db.getCollection('wwactivities').find({ userId: "2c48bc64-76cd-41b0-88af-b8dfea667960", "activity.completedAt": { $lte: new Date(1525103999999) } })
2. Scala驱动端的日期处理最佳实践
既然你用的是mongo-scala-driver 2.1.0,代码里的日期处理也得规范,避免生成的查询自带“日期转Long”的坑:
- 优先用
java.time.Instant或者org.joda.time.DateTime(驱动2.x版本支持Joda时间,3.x之后转向Java 8时间API)构造日期,别直接传长整型时间戳。 - 给你个示例代码参考:
import org.mongodb.scala._ import org.mongodb.scala.model.Filters._ import java.time.Instant // 初始化客户端和集合 val mongoClient = MongoClient() val database = mongoClient.getDatabase("your_database_name") val collection = database.getCollection("wwactivities") // 构造目标日期(完整ISO格式) val targetCompletedAt = Instant.parse("2018-04-30T23:59:59.999Z") // 组装查询条件 val query = and( equal("userId", "2c48bc64-76cd-41b0-88af-b8dfea667960"), lte("activity.completedAt", targetCompletedAt) ) // 执行查询 collection.find(query).subscribe( doc => println(s"匹配到文档: $doc"), err => println(s"查询出错: ${err.getMessage}"), () => println("查询完成") )
这样生成的查询会正确使用ISODate类型,不会转成Long,在Shell里查看查询日志也能看到正确的日期格式。
3. 验证过滤器的类型是否正确
你可以在Shell里先打印过滤器,确认它的类型是不是ISODate:
var filter = { userId: "2c48bc64-76cd-41b0-88af-b8dfea667960", "activity.completedAt": { $lte: ISODate("2018-04-30T23:59:59.999Z") } } printjson(filter)
如果输出里"activity.completedAt.$lte"的类型是ISODate("...")而不是数字,说明过滤器是对的;如果是数字,那就是日期字符串格式的问题,得重新调整格式。
内容的提问来源于stack exchange,提问作者luddy2018
相关产品推荐
相关产品推荐

