You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel MongoDB中whereMonth/whereYear查询返回空集合问题

问题根因

whereMonth/whereYear这类日期查询方法在jenssegers MongoDB扩展包中的实现逻辑和SQL场景完全不同:

  • 该类方法仅对存储类型为MongoDB原生BSON UTCDateTime(即ISODate)的字段生效,不会自动解析字符串、整型时间戳格式的日期值做月份/年份提取
  • 只要created_at字段不是正确的BSON日期类型,查询条件就不会命中任何文档,直接返回空集合。参数格式问题只是次要影响因素:MongoDB日期提取返回的月份是1-12的整型值,带前导零的字符串(比如'06')会因为类型不匹配无法命中结果,但这不是你当前查询返回空的核心原因。
排查修复方案
  • 第一步:核对字段存储类型
    直接连接MongoDB查询单条文档,确认created_at字段的存储格式:正确格式为ISODate("2024-06-01T00:00:00Z"),如果是字符串、整型时间戳,说明字段类型不符合查询要求。
  • 第二步:核对模型配置
    检查MyModel的配置,确保没有手动将created_at排除出自动维护的日期字段列表;Laravel 8及以上版本需要确认$casts中对created_at的日期类型配置正确,不要自定义会输出纯字符串的$dateFormat导致存库时类型转换失效,参考配置:
    protected $casts = [
        'created_at' => 'datetime',
        'updated_at' => 'datetime',
    ];
    
    配置修正后,新增的文档会自动写入正确的BSON日期类型;存量的非日期类型数据需要写一次性脚本批量转换为ISODate格式,转换完成后whereMonth/whereYear就可以正常返回结果。
  • 临时兼容方案(不修改存量数据时使用)
    如果暂时无法调整存量数据格式,可以直接调用whereRaw写Mongo原生聚合查询实现相同的筛选效果,查询6月数据的示例:
    $collection = MyModel::whereRaw([
        '$expr' => [
            '$eq' => [
                ['$month' => '$created_at'],
                6
            ]
        ]
    ])->get();
    
    按年份筛选只需要把表达式里的$month替换为$year,对应传入整型年份值即可。如果created_at存的是整型时间戳,需要先在原生表达式中用$toDate把字段值转为日期类型再做月份/年份提取。

提示:传入月份参数时直接使用1-12的整型值即可,不要使用带前导零的字符串,否则会因为类型不匹配导致查询失效。

内容的提问来源于stack exchange,提问作者Gabriel Chenaouy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 09:54:23