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

PHP MongoDB:使用表达式过滤字符串格式的日期范围数据

PHP查询MongoDB字符串日期范围的问题解决

问题场景

需要查询MongoDB集合中指定日期范围内的文档,但集合中的Date字段是字符串类型,格式为Tue, 06 Apr 93 12:03:11 GMT。

集合文档结构:

{
  "Number": "12345",
  "Date": "Tue, 06 Apr 93 12:03:11 GMT"
}

用户尝试的代码(无法正常运行):

$start_date = new MongoDB\BSON\UTCDateTime(strtotime($_GET['datep']) * 1000);
$end_date = new MongoDB\BSON\UTCDateTime(strtotime($_GET['datek']) * 1000);

$filter = [
    'Newsgroups' => ['$regex' => ".*".$_GET['group'].".*"],
    '$and' => [
        [ '$expr' => [ '$gte' => [ '$dateFromString' => [ 'dateString' => '$Date'] , $start_date ] ] ],
        [ '$expr' => [ '$lte' => [ '$dateFromString' => [ 'dateString' => '$Date'] , $end_date ] ] ],
    ],
]; 
$query = new MongoDB\Driver\Query($filter, []);
$cursor = $connection->executeQuery('newscol.news',$query);

执行后报错:

代表表达式的对象必须恰好有一个字段:{ $dateFromString: { dateString: "$Date" }, 0: new Date(733968000000) }

错误原因

  • $dateFromString缺少日期格式指定:MongoDB无法自动识别Tue, 06 Apr 93 12:03:11 GMT这种自定义格式,必须显式声明匹配的格式规则。
  • $gte/$lte表达式语法错误:$dateFromString作为转换表达式需要完整包裹在数组中,且参数顺序需遵循「转换后的字段值在前,目标日期在后」的规则。
  • 冗余的表达式嵌套:原代码将$expr拆分到$and的子条件中,导致语法结构混乱。

修正后的代码

// 处理传入的日期参数,转换为MongoDB UTC日期对象
$startTimestamp = strtotime($_GET['datep']);
$endTimestamp = strtotime($_GET['datek']);

// 确保日期解析有效,若strtotime不兼容传入格式,建议用DateTime类手动解析
$start_date = new MongoDB\BSON\UTCDateTime($startTimestamp * 1000);
$end_date = new MongoDB\BSON\UTCDateTime($endTimestamp * 1000);

$filter = [
    'Newsgroups' => ['$regex' => ".*".preg_quote($_GET['group']).".*"], // 转义正则特殊字符,避免注入
    '$expr' => [
        '$and' => [
            [
                '$gte' => [
                    ['$dateFromString' => [
                        'dateString' => '$Date',
                        'format' => 'D, d M y H:i:s T' // 匹配原日期的格式规则
                    ]],
                    $start_date
                ]
            ],
            [
                '$lte' => [
                    ['$dateFromString' => [
                        'dateString' => '$Date',
                        'format' => 'D, d M y H:i:s T'
                    ]],
                    $end_date
                ]
            ]
        ]
    ]
];

$query = new MongoDB\Driver\Query($filter, []);
$cursor = $connection->executeQuery('newscol.news', $query);

额外优化建议

  • 正则安全:使用preg_quote()转义$_GET['group']中的特殊字符,避免正则注入风险。
  • 日期解析兼容性:若strtotime无法正确解析传入的日期格式,改用DateTime类手动指定格式解析:
    $startDate = DateTime::createFromFormat('Y-m-d', $_GET['datep']); // 替换为实际传入的日期格式
    $startTimestamp = $startDate->getTimestamp();
    
  • 长期性能优化:如果频繁执行此类查询,建议批量将Date字段转换为MongoDB原生日期类型,避免每次查询都进行字符串转日期的计算。

内容的提问来源于stack exchange,提问作者Kacper K

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 17:52:52