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

MongoDB聚合查询实现按Symbol分组获取指定日期最新单条记录

获取MongoDB中指定日期每个Symbol的最新记录

没问题,我来帮你搞定这个聚合查询。要实现每个symbol在指定日期的最新记录,我们可以用MongoDB的聚合框架,结合几个关键阶段来完成,还能利用你现有的索引提升性能。

完整聚合查询语句

db.yourCollectionName.aggregate([
  // 筛选2021-10-17当天的所有记录
  {
    $match: {
      "times.event_ts_utc": {
        $gte: ISODate("2021-10-17T00:00:00.000Z"),
        $lt: ISODate("2021-10-18T00:00:00.000Z")
      }
    }
  },
  // 按symbol分组前先排序,确保每个symbol的最新记录排在最前面
  {
    $sort: {
      "symbol": 1,
      "times.event_ts_utc": -1
    }
  },
  // 按symbol分组,取每个组的第一条(最新)记录
  {
    $group: {
      _id: "$symbol",
      latestRecord: { $first: "$$ROOT" }
    }
  },
  // 将嵌套的最新记录展开为顶层文档,匹配预期输出格式
  {
    $replaceRoot: { newRoot: "$latestRecord" }
  }
])

各阶段详细解释

  • $match阶段:精准过滤出2021-10-17当天的所有数据,用$gte(当日零点)和$lt(次日零点)的范围查询比直接匹配日期更准确,还能触发你已有的idx_times.event_ts_utc索引,大幅减少后续需要处理的数据量。
  • $sort阶段:先按symbol升序排列,再按times.event_ts_utc降序排列。这样同一个symbol下的记录,时间最晚的会排在该组的最前面。如果数据量特别大,建议创建{symbol:1, times.event_ts_utc:-1}的复合索引,能让排序操作完全走索引,避免内存排序的性能瓶颈。
  • $group阶段:以symbol作为分组键,用$first操作符提取每个组的第一条记录(也就是刚才排序后最新的那条)。$$ROOT代表当前完整的文档对象,这样我们就能把整条最新记录保存到latestRecord字段中。
  • $replaceRoot阶段:把latestRecord字段里的内容替换为顶层文档结构,让输出格式和你预期的完全一致——每个文档都是独立的、对应symbol的最新记录。

动态获取“昨日”数据的优化

如果你的需求不是固定日期,而是要动态获取“昨日”的最新记录,可以用JavaScript生成日期范围:

// 生成昨日的开始和结束时间
const yesterdayStart = new Date();
yesterdayStart.setDate(yesterdayStart.getDate() - 1);
yesterdayStart.setHours(0, 0, 0, 0);

const yesterdayEnd = new Date(yesterdayStart);
yesterdayEnd.setDate(yesterdayEnd.getDate() + 1);

// 将上述变量代入$match阶段
db.yourCollectionName.aggregate([
  {
    $match: {
      "times.event_ts_utc": {
        $gte: yesterdayStart,
        $lt: yesterdayEnd
      }
    }
  },
  // 后续阶段和之前一致
  { $sort: { "symbol": 1, "times.event_ts_utc": -1 } },
  { $group: { _id: "$symbol", latestRecord: { $first: "$$ROOT" } } },
  { $replaceRoot: { newRoot: "$latestRecord" } }
])

索引优化建议

虽然你现有的idx_symbol和idx_times.event_ts_utc单字段索引能支持查询,但创建{symbol:1, times.event_ts_utc:-1}的复合索引会让整个聚合流程更高效——它能同时满足$match和$sort的需求,避免MongoDB在内存中进行大量排序操作,尤其适合你提到的“数据量庞大”的场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.01 01:42:35