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

如何用PHP在MongoDB中查询日期范围内的多层结构记录?

解决方案

1. 重构数据结构(最优方案)

你当前把日期作为文档键名的设计,是导致查询困难的核心原因。MongoDB的查询逻辑依赖字段值而非动态键名,建议将日期改为字段值,调整后的结构可以有两种选择:

选项A:单数据类型单文档

{
  "_id": ObjectId("..."),
  "date": "2020-07",
  "data_type": "MedianListPrice",
  "value": { /* 对应的数据内容 */ }
}

选项B:单日期多数据类型文档

{
  "_id": ObjectId("..."),
  "date": "2020-07",
  "MedianListPrice": { /* 对应的数据内容 */ },
  "MonthOfSupply": { /* 对应的数据内容 */ }
}

重构后,就能轻松实现日期范围+条件查询,PHP代码示例:

// 查询2020-07至2020-09期间,MedianListPrice超过50万的记录
$filter = [
  'date' => [
    '$gte' => '2020-07',
    '$lte' => '2020-09'
  ],
  'MedianListPrice.price' => ['$gt' => 500000]
];
$cursor = $collection->find($filter);

2. 临时过渡方案(不推荐用于大数据量)

如果暂时无法重构结构,可以用MongoDB的聚合管道,通过$objectToArray将动态键转为键值对数组后过滤,PHP代码示例:

$pipeline = [
  // 将根文档转为键值对数组
  ['$project' => ['data' => ['$objectToArray' => '$$ROOT']]],
  // 展开数组,每个元素对应一个日期键的内容
  ['$unwind' => '$data'],
  // 过滤日期范围与子数据条件
  ['$match' => [
    'data.k' => [
      '$gte' => '2020-07',
      '$lte' => '2020-08'
    ],
    'data.v.MedianListPrice.some_field' => ['$gt' => 100]
  ]],
  // 按需重组结果结构
  ['$group' => [
    '_id' => null,
    'matched_records' => ['$push' => '$data']
  ]]
];

$result = $collection->aggregate($pipeline);

注意:该方案需要全表扫描,无法利用索引,数据量大时性能极差,仅适合临时过渡。

3. 性能优化建议

重构结构后,务必给日期字段添加索引,提升查询速度:

// 单字段索引
$collection->createIndex(['date' => 1]);
// 复合索引(针对日期+子字段的组合查询)
$collection->createIndex(['date' => 1, 'MedianListPrice.price' => 1]);

内容的提问来源于stack exchange,提问作者Palanivel Rajan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 22:01:07