MongoDB查询任意日期8-18点UTC时间记录报错及实现问题
问题原因
你写的查询报错是因为$expr运算符仅支持传入单个聚合表达式作为入参,直接在$expr对象下平级放置$gte、$lte两个表达式字段不符合MongoDB聚合语法规则,多条件并列判断需要通过$and运算符包裹所有条件。
原生MongoDB查询写法
正确的查询语句如下,注意$hour默认返回UTC时间的0-23格式小时值,和你存储的UTC时间格式直接匹配:
db.你的集合名.find({ $expr: { $and: [ { $gte: [ { $hour: "$DateTime" }, 8 ] }, { $lte: [ { $hour: "$DateTime" }, 18 ] } ] } })
如果后续需要按指定时区计算小时(比如东八区业务时间),可以给$hour传入时区参数即可:
// 按东八区时间计算小时范围 { $hour: { date: "$DateTime", timezone: "Asia/Shanghai" } }
.NET Core 环境实现方案
首先确保项目已安装官方MongoDB.Driver NuGet包,提供两种常用实现方式:
1. 稳定通用写法(兼容所有驱动版本)
通过FilterDefinitionBuilder结合Expr方法构建查询,不需要依赖驱动的Linq翻译能力:
// 初始化集合实例 var collection = db.GetCollection<你的实体类>("你的集合名"); // 构建提取小时的公共表达式 var getHourExpr = new BsonDocument("$hour", "$DateTime"); // 组合查询条件 var filter = Builders<你的实体类>.Filter.And( Builders<你的实体类>.Filter.Expr(new BsonDocument("$gte", new BsonArray { getHourExpr, 8 })), Builders<你的实体类>.Filter.Expr(new BsonDocument("$lte", new BsonArray { getHourExpr, 18 })) ); // 执行查询 var queryResult = await collection.Find(filter).ToListAsync();
2. Lambda强类型写法(推荐2.18.0+版本驱动使用)
高版本MongoDB驱动支持自动将DateTime的Hour属性访问翻译成$hour聚合表达式,写法和普通Linq查询完全一致:
var queryResult = await collection.AsQueryable() .Where(x => x.DateTime.Hour >= 8 && x.DateTime.Hour <= 18) .ToListAsync();
性能优化提示
上述写法都属于运行时计算字段的查询,无法命中集合索引,数据量较大时查询延迟会明显升高。如果该查询是高频场景,建议在文档中额外冗余一个DateTimeHour字段,存储对应记录UTC时间的小时数值,给该字段创建升序索引后直接按字段范围匹配,性能会有数量级提升。
内容的提问来源于stack exchange,提问作者Ankush Madankar
相关产品推荐
相关产品推荐

