MongoDB 5.0 C#驱动时序集合按时间范围过滤返回零结果问题
问题原因
- C# 中
DateTime与TimeSpan相加后,返回的新DateTime对象的Kind属性会被重置为Unspecified,即使原始DateTime明确指定为Utc类型。MongoDB C# 驱动解析查询条件时,会将Kind为Unspecified的时间按照本地时区转换为 UTC 时间,导致最终传给数据库的查询时间范围与预期不符。 - 若实体类
MongoTimeSeriesDocument中的Timestamp字段定义为BsonDateTime类型,Lambda 表达式解析时会出现类型匹配异常,驱动无法正确生成时间比较的查询条件。 - 低版本 MongoDB C# 驱动对 5.0+ 时序集合的查询优化存在已知缺陷,当查询时间下限早于集合所有文档的最小时间时,会错误返回 0 条结果。
- 需确认集合内
Timestamp字段实际存储类型为 BSON Date 类型,若存储为字符串、时间戳数字等类型,也会导致时间范围匹配失败。
解决方案
- 修复时间Kind丢失问题
计算完时间边界后手动指定Kind为Utc:
var baseTime = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); var dt1 = DateTime.SpecifyKind(baseTime + from, DateTimeKind.Utc); var dt2 = DateTime.SpecifyKind(baseTime + to, DateTimeKind.Utc);
统一时间字段类型
将实体类的Timestamp字段类型修改为DateTime,无需手动使用BsonDateTime类型。你已注册 UTC 时间序列化器,驱动会自动将DateTime序列化为 BSON Date 类型,完全符合时序集合的要求,避免类型解析异常。改用字段名指定过滤条件
如果Lambda表达式解析始终异常,直接通过字段名构造过滤条件,跳过表达式解析步骤:
var filter = Builders<MongoTimeSeriesDocument>.Filter.Gte("Timestamp", dt1); filter &= Builders<MongoTimeSeriesDocument>.Filter.Lte("Timestamp", dt2);
升级驱动版本
将 MongoDB C# 驱动升级到 2.19 及以上正式版本,修复时序集合相关的查询bug。提前验证查询逻辑
先在Mongo Shell中执行相同逻辑的查询,确认数据本身符合预期:
# 替换为你的集合名,验证时间范围查询是否正常 db.你的集合名.count({Timestamp: {$gte: ISODate("1970-01-01T00:00:00Z"), $lte: ISODate("2021-12-31T00:00:00Z")}})
内容的提问来源于stack exchange,提问作者deafjeff
相关产品推荐
相关产品推荐

