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

MongoDB按条件计算活动时间差:统计总时长、暂停时长等

解决方案:MongoDB聚合管道计算活动时间

假设你的集合文档结构如下(示例):

{
  "_id": ObjectId("65d2f1b7a1b2c3d4e5f6a7b8"),
  "Log": [
    { "status": "Start", "time": ISODate("2024-01-01T09:00:00Z") },
    { "status": "Hold", "time": ISODate("2024-01-01T09:30:00Z") },
    { "status": "Holdrelease", "time": ISODate("2024-01-01T10:15:00Z") },
    { "status": "pause", "time": ISODate("2024-01-01T11:00:00Z") },
    { "status": "pauserelease", "time": ISODate("2024-01-01T11:20:00Z") },
    { "status": "Hold", "time": ISODate("2024-01-01T11:40:00Z") },
    { "status": "Holdrelease", "time": ISODate("2024-01-01T11:50:00Z") },
    { "status": "Finish", "time": ISODate("2024-01-01T12:00:00Z") }
  ]
}

使用以下聚合管道计算所需时间:

db.yourCollection.aggregate([
  // 提取StartTime和FinishTime,同时保留完整Log数组
  {
    $addFields: {
      startTime: { $first: { $filter: { input: "$Log", cond: { $eq: ["$$this.status", "Start"] } } }.time },
      finishTime: { $first: { $filter: { input: "$Log", cond: { $eq: ["$$this.status", "Finish"] } } }.time }
    }
  },
  // 计算总耗时totalTime(毫秒)
  {
    $addFields: {
      totalTime: { $subtract: ["$finishTime", "$startTime"] }
    }
  },
  // 遍历Log数组,累计holdTime和pauseTime
  {
    $addFields: {
      timeStats: {
        $reduce: {
          input: "$Log",
          initialValue: { holdTime: 0, pauseTime: 0, lastHoldTime: null, lastPauseTime: null },
          in: {
            holdTime: {
              $cond: [
                { $eq: ["$$this.status", "Holdrelease"] },
                { $add: ["$$value.holdTime", { $subtract: ["$$this.time", "$$value.lastHoldTime"] }] },
                "$$value.holdTime"
              ]
            },
            pauseTime: {
              $cond: [
                { $eq: ["$$this.status", "pauserelease"] },
                { $add: ["$$value.pauseTime", { $subtract: ["$$this.time", "$$value.lastPauseTime"] }] },
                "$$value.pauseTime"
              ]
            },
            lastHoldTime: {
              $cond: [
                { $eq: ["$$this.status", "Hold"] },
                "$$this.time",
                "$$value.lastHoldTime"
              ]
            },
            lastPauseTime: {
              $cond: [
                { $eq: ["$$this.status", "pause"] },
                "$$this.time",
                "$$value.lastPauseTime"
              ]
            }
          }
        }
      }
    }
  },
  // 提取holdTime、pauseTime并计算workTime
  {
    $addFields: {
      holdTime: "$timeStats.holdTime",
      pauseTime: "$timeStats.pauseTime",
      workTime: { $subtract: ["$totalTime", { $add: ["$timeStats.holdTime", "$timeStats.pauseTime"] }] }
    }
  },
  // 保留需要的字段(可选)
  {
    $project: {
      _id: 1,
      totalTime: 1,
      holdTime: 1,
      pauseTime: 1,
      workTime: 1,
      // 如果需要保留原始Log可以加上:Log: 1
    }
  }
])

关键逻辑说明:

  • 提取StartTime/FinishTime:用$filter从Log数组中筛选出对应状态的条目,再取时间(假设每个文档只有一个Start和一个Finish)
  • 计算totalTime:直接用Finish时间减去Start时间,结果是毫秒数
  • 累计Hold/Pause时长:用$reduce遍历Log数组,记录上一次Hold/pause的时间,当遇到对应的release状态时,计算时长并累计到总时长中
  • 计算workTime:总时长减去Hold和Pause的总时长

注意事项:

  • 确保每个Hold都有对应的Holdrelease,每个pause都有对应的pauserelease,否则未匹配的状态不会被计入时长
  • 如果需要转换为秒/分钟,可以在最后添加阶段用$divide(比如{ $divide: ["$totalTime", 1000] }转为秒)
  • 如果文档中可能存在多个Start/Finish,需要根据业务逻辑调整筛选方式(比如取最早的Start和最晚的Finish)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 14:32:21