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

如何在MongoDB中对对象内部排序并计算对象内数值差值

MongoDB 数据处理需求实现方案

前置要求

本方案用到了MongoDB 5.2版本新增的$sortArray、$shift运算符,需确保你的MongoDB服务版本≥5.2,低版本可通过$unwind+$sort+$group的组合替换对应逻辑。

完整聚合查询代码

db.collection.aggregate([
  // 拆解外层data的日期键为数组格式
  {
    $project: {
      dateItems: { $objectToArray: "$data" }
    }
  },
  // 展开日期数组,每个日期对应一条独立文档
  { $unwind: "$dateItems" },
  // 拆解每个日期下的小时键,拼接为完整ISO时间格式
  {
    $project: {
      date: "$dateItems.k",
      hourItems: {
        $map: {
          input: { $objectToArray: "$dateItems.v" },
          as: "hourItem",
          in: {
            time: { $concat: [ "$dateItems.k", "T", "$$hourItem.k", ":00:00:0Z" ] },
            value: "$$hourItem.v"
          }
        }
      }
    }
  },
  // 对单日内的所有时间点按时间升序排序
  {
    $project: {
      date: 1,
      sortedHourItems: { $sortArray: { input: "$hourItems", sortBy: { time: 1 } } }
    }
  },
  // 提取单日最早、最晚时间和对应值,统计当日数值数量
  {
    $project: {
      date: 1,
      dayFirstTime: { $first: "$sortedHourItems.time" },
      dayFirstValue: { $first: "$sortedHourItems.value" },
      dayLastTime: { $last: "$sortedHourItems.time" },
      dayLastValue: { $last: "$sortedHourItems.value" },
      dayCount: { $size: "$sortedHourItems" }
    }
  },
  // 窗口函数获取前一日的最晚时间和对应值,用于单日单值场景计算
  {
    $setWindowFields: {
      sortBy: { date: 1 },
      output: {
        prevDayLastValue: {
          $shift: {
            output: "$dayLastValue",
            by: -1,
            default: null
          }
        },
        prevDayLastTime: {
          $shift: {
            output: "$dayLastTime",
            by: -1,
            default: null
          }
        }
      }
    }
  },
  // 按规则计算差值,输出符合要求的文档结构
  {
    $project: {
      _id: 0,
      data: {
        time_first: {
          $cond: {
            if: { $gt: [ "$dayCount", 1 ] },
            then: "$dayFirstTime",
            else: "$prevDayLastTime"
          }
        },
        value_first: {
          $cond: {
            if: { $gt: [ "$dayCount", 1 ] },
            then: "$dayFirstValue",
            else: "$prevDayLastValue"
          }
        },
        time_last: "$dayLastTime",
        value_last: "$dayLastValue",
        "difference_value_last-value_first": {
          $subtract: [
            "$dayLastValue",
            {
              $cond: {
                if: { $gt: [ "$dayCount", 1 ] },
                then: "$dayFirstValue",
                else: "$prevDayLastValue"
              }
            }
          ]
        }
      }
    }
  }
])

逻辑说明

  • 首先通过$objectToArray把嵌套的对象结构转为可遍历的数组,方便拼接完整时间字符串
  • 用$sortArray对单日内的时间点按时间排序,直接提取首尾值作为单日的first、last值
  • 通过窗口函数$setWindowFields的$shift操作取到前一日的last值,解决单日仅1个值的计算场景
  • 最后用$cond判断当日数值数量,按规则生成最终的first值和差值

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 01:12:02