【问题标题】:Calculate amount of minutes between multiple date ranges, but don't calculate the overlapping dates in MongoDB计算多个日期范围之间的分钟数,但不计算 MongoDB 中的重叠日期
【发布时间】:2020-07-08 16:39:33
【问题描述】:

我正在创建一种方法来生成在给定时间范围内设备停机时间量的报告。我可能会处理 100 到数千个文档。每个文档都有一个开始日期和结束日期,两者都是 BSON 格式,并且通常在几分钟内。为简单起见,我还将秒数归零。

我需要做的实际聚合是我需要计算每个给定日期之间的分钟数,但可能还有其他日期重叠的文档。如果已经计算过,则不应计算任何重叠时间。我还需要进行各种其他聚合,但这是我唯一不确定的聚合,如果它甚至可能的话。

{
  "StartTime": "2020-07-07T18:10:00.000Z",
  "StopTime": "2020-07-07T18:13:00.000Z",
  "TotalMinutesDown": 3,
  "CreatedAt": "2020-07-07T18:13:57.675Z"
}

{
  "StartTime": "2020-07-07T18:12:00.000Z",
  "StopTime": "2020-07-07T18:14:00.000Z",
  "TotalMinutesDown": 2,
  "CreatedAt": "2020-07-07T18:13:57.675Z"
}

上面的两个文档是我正在使用的示例。每个文档都获取存储在文档中的两个日期之间的总分钟数(此字段用于另一个目的,不相关)。如果我要聚合它以减少总分钟数,总分钟数的输出应该是 4,因为我不想计算重叠的分钟数。

【问题讨论】:

    标签: mongodb aggregation-framework


    【解决方案1】:

    在我看来,寻找时间范围的重叠听起来有点抽象。我们试着把它转换成数据库常用的一个概念:离散值。

    如果我们将时间转换为离散值,我们将能够找到重复值,即“重叠值”并消除它们。

    我将使用您的示例数据说明这些步骤。由于您已将秒数归零,为简单起见,我们可以从那里开始。

    1. 由于我们关心 分钟 增量,我们将把时间转换为自 Unix 纪元以来经过的“分钟”。
    {
      "StartMinutes": 26569090,
      "StopMinutes": 26569092,
    }
    
    {
      "StartMinutes": 26569092,
      "StopMinutes": 26569092
    }
    
    
    1. 我们将它们转换为离散值
    {
      "minutes": [26569090, 26569091, 26569092]
    }
    
    {
      "minutes": [26569092, 26569093]
    }
    
    1. 然后我们可以对所有数组进行集合并集
    {
      "allMinutes": [26569090, 26569091, 26569092, 26569093]
    }
    

    这就是我们如何使用聚合获得解决方案。我已经简化了查询并将一些操作组合在一起

    db.collection.aggregate({
      $project: {
        minutes: {
          $range: [
            {
              $divide: [{ $toLong: "$StartTime" }, 60000] // convert to minutes timestamp
            },
            {
              $divide: [{ $toLong: "$StopTime" }, 60000]
            }
          ]
        },
      }
    },
    {
      $group: { // combine to one document
        _id: null,
        _temp: { $push: "$minutes" }
      }
    },
    {
      $project: {
        totalMinutes: {
          $size: { // get the size of the union set
            $reduce: {
              input: "$_temp",
              initialValue: [],
              in: {
                $setUnion: ["$$value", "$$this"] // combine the values using set union
              }
            }
          }
        }
      }
    })
    

    Mongo Playground

    【讨论】:

    • 哇!在过去的几天里,我整天都在与这个作斗争,只是无法理解它。我曾尝试转换为时代,但并不真正知道从那里去哪里。你是救生员!感谢您的帮助
    猜你喜欢
    • 2023-01-19
    • 1970-01-01
    • 2014-01-06
    • 1970-01-01
    • 2019-08-16
    • 1970-01-01
    • 2020-02-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多