如何在Mongoose的Mongo聚合$week操作中纳入时区?
解决$week聚合带时区时的MongoError问题
看起来你碰到的这个错误,核心原因大概率是MongoDB版本不支持带timezone参数的$week语法,少数情况下也可能是字段类型不符。我来给你拆解下问题和解决办法:
为什么会报错?
在MongoDB 3.6版本之前,$week聚合操作符只接受一个纯日期表达式作为参数(比如直接写$week: "$exit_time"),完全不支持{ date: "...", timezone: "..." }这种对象格式的参数。当你用这种写法时,MongoDB会把整个对象当成要转换为Date的输入,自然就会抛出"can't convert from BSON type object to Date"的错误。
另外,也可以快速排查下exit_time字段是否全都是Date类型——虽然你不带时区时能正常运行,但万一有个别文档的该字段是字符串或其他类型,也可能触发这个错误。可以用这条命令检查:
db.yourCollection.find({ exit_time: { $type: { $ne: "date" } } })
解决方案
方案1:升级MongoDB到3.6+(推荐)
如果你的环境允许升级,升级到3.6或更高版本后,就可以直接使用带时区的$week语法,写法完全符合你尝试的文档示例:
db.yourCollection.aggregate([ { $group: { _id: { $week: { date: "$exit_time", timezone: "Asia/Shanghai" // 支持IANA时区(比如"America/New_York")或偏移量(比如"+08:00") } }, totalDocs: { $sum: 1 } // 可以加统计字段,按需调整 } } ])
方案2:不升级版本,用$dateToString间接实现
如果没法升级,可以先用$dateToString将日期按指定时区转换为包含周数的字符串,再按这个字符串分组:
db.yourCollection.aggregate([ { $project: { // 选合适的周数格式:%U(周日为一周开始)、%V(ISO周,周一为开始)、%W(周一为开始) weekNumber: { $dateToString: { format: "%V", date: "$exit_time", timezone: "Asia/Shanghai" } } } }, { $group: { _id: "$weekNumber", totalDocs: { $sum: 1 } } } ])
这样就能绕过版本限制,实现带时区的周数分组啦。
内容的提问来源于stack exchange,提问作者Ryley Matos
相关产品推荐
相关产品推荐

