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

如何将MySQL每日加密货币价格统计插入查询转换为MongoDB聚合查询?

解决MongoDB聚合实现每日加密货币价格统计的问题

我来帮你把MySQL的统计逻辑转换成正确的MongoDB聚合管道,先分析你的需求和之前的错误,再给出完整的解决方案:

核心需求回顾

你需要按slug分组,统计当日加密货币的以下指标:

  • priceUsd和priceBtc的平均值
  • priceUsd的最高价(high)和最低价(low)
  • 当日最早更新的priceUsd(open)和最晚更新的priceUsd(close)
  • 保留volumeUsd24h和marketcapUsd(MySQL中是取分组内任意一行的值,这里我们用$first匹配原逻辑)
  • 将结果写入DemoDaily集合,按slug排序

错误分析(你的原代码问题)

  1. 聚合阶段顺序错误:你把$project放在了$group之前,这会导致$avg、$max这类聚合函数无法对分组后的数据计算——$group才是分组聚合的核心阶段,必须放在统计计算之前。
  2. open/close字段逻辑错误:你使用了不存在的$sortBy操作符,MongoDB无法直接通过这种方式获取排序后的首尾值,需要先全局排序再用$first/$last提取。
  3. $group阶段缺失聚合字段:你的$group只指定了slug作为分组键,完全没包含需要计算的统计字段,自然无法生成所需结果。

正确的MongoDB聚合代码

// 构造当日的时间范围(替换成你的$today变量,比如new Date('2021-09-07'))
const today = new Date(); // 假设当前日期为目标统计日
const startOfDay = new Date(today.getFullYear(), today.getMonth(), today.getDate());
const endOfDay = new Date(startOfDay);
endOfDay.setDate(endOfDay.getDate() + 1);

const result = await DemoHourly.aggregate([
  // 1. 筛选当日的数据:匹配lastUpdated在当天00:00到次日00:00之间
  {
    $match: {
      lastUpdated: {
        $gte: startOfDay,
        $lt: endOfDay
      }
    }
  },
  // 2. 先按slug分组排序,再按lastUpdated升序排序,确保后续$first/$last能拿到正确的open/close
  {
    $sort: {
      slug: 1,
      lastUpdated: 1
    }
  },
  // 3. 按slug分组,计算所有统计指标
  {
    $group: {
      _id: "$slug", // 用slug作为分组唯一标识
      avgPriceUsd: { $avg: "$priceUsd" },
      avgPriceBtc: { $avg: "$priceBtc" },
      high: { $max: "$priceUsd" },
      low: { $min: "$priceUsd" },
      open: { $first: "$priceUsd" }, // 升序排序后的第一个值就是当日最早价格
      close: { $last: "$priceUsd" }, // 升序排序后的最后一个值就是当日最晚价格
      volumeUsd24h: { $first: "$volumeUsd24h" }, // 取分组内第一个的24h成交量(匹配MySQL逻辑)
      marketcapUsd: { $first: "$marketcapUsd" }, // 取分组内第一个的市值(匹配MySQL逻辑)
      date: { $first: startOfDay } // 设置当日起始时间作为统计日期
    }
  },
  // 4. 整理输出字段:把_id转为slug,让结构更清晰(可选)
  {
    $project: {
      _id: 0,
      slug: "$_id",
      avgPriceUsd: 1,
      avgPriceBtc: 1,
      volumeUsd24h: 1,
      marketcapUsd: 1,
      high: 1,
      low: 1,
      open: 1,
      close: 1,
      date: 1
    }
  },
  // 5. 按slug升序排序
  {
    $sort: {
      slug: 1
    }
  },
  // 6. 将结果写入DemoDaily集合:注意$out会替换整个集合,若要增量更新可改用$merge
  {
    $out: "DemoDaily"
  }
]);

关键逻辑说明

  1. 时间范围筛选:用$gte和$lt匹配完整的当日时间段,避免直接匹配日期字符串,确保时间精度正确。
  2. 排序的作用:先按slug和lastUpdated升序排序,这样在$group阶段用$first就能拿到当日最早价格(open),$last拿到最晚价格(close),完美对应MySQL中GROUP_CONCAT取首尾的逻辑。
  3. $group阶段的聚合:
    • $avg/$max/$min直接对应MySQL的AVG()/MAX()/MIN()
    • $first用于获取分组内的第一个值,对应MySQL中未聚合字段的取任意行逻辑
  4. 增量更新提示:如果不需要覆盖DemoDaily集合,而是增量更新已有数据,可以把$out换成$merge,配置匹配条件为slug和date来更新重复数据。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 11:38:14