【问题标题】:Splitting into time buckets when grouping by name按名称分组时拆分为时间段
【发布时间】:2017-10-26 19:43:19
【问题描述】:

我有一个 MongoDB 集合,division_entry。

我希望按标签过滤,然后按时间和独特的不同值进行存储。 最后,我想要在给定时间跨度内所有不同的唯一值。

目前,我必须在代码中存储并按时间跨度进行调用。这会导致调用过多。 现在 -

db.division_entry.aggregate([{ $match : { $and : [ { "division.label" : “ABCD”},{“时间戳”:{$gt:1495448249635,$lt:1495448249641}} ] } } , {$group : { _id : "$unique"} } , {$count : "value" }])

非常感谢您对实际结果的帮助。

编辑: 更多详情:

{
            "_id" : "1",
            "timestamp" : NumberLong("1495448249640"),
            "unique" : "One",
            "division" : [
                    {
                            "label" : "ABCD"
                    }
            ]
    }
    {
            "_id" : "3",
            "timestamp" : NumberLong("1495448249636"),
            "unique" : "Two",
            "division" : [
                    {
                            "label" : "ABCD"
                    }
            ]
    }
    {
            "_id" : "2",
            "timestamp" : NumberLong("1495448249650"),
            "unique" : "Two",
            "division" : [
                    {
                            "label" : "ABCD"
                    }
            ]
    }

db.division_entry.aggregate([{ $match : { $and : [ { "division.label": "ABCD"}, { "timestamp" : { $gt: 1495448249635, $lt: 1495448249651 }} ] } } , {$group : { _id : "$unique"} }])
         { "_id" : "Two" }
         { "_id" : "One" }

db.division_entry.aggregate([{ $match : { $and : [ { "division.label" : "ABCD"}, { "timestamp" : { $gt: 1495448249635, $lt: 1495448249651 } } ] } } , {$group : { _id : "$unique"} } , {$count : "value" }])
        { "value" : 2 }

这是在匹配查询中指定的特定时间范围内完成的。假设我想要一天数据的一分钟粒度,我将不得不进行 1440 次这样的调用,其中每次调用的时间戳范围将涵盖一分钟。

我需要帮助来同时为“唯一”字段存储和查找不同的值。

【问题讨论】:

  • 这里的实际分组是什么?您是否也应该看到不同的 "timestamp" 或者只是“时间戳桶”中不同的 "unique" 值?从你的问题和这么小的样本中很难说出来。有几种技术可以解决此问题,但您包含的聚合管道示例无效也无济于事。如果您可以编辑以澄清这些观点,最好是预期的输出,那么它将有助于您的问题。
  • 如果您可以指定您的“存储桶”是非常简单的东西,例如“定期间隔”(即 1 分钟、1 小时等),那么这也会让事情变得更加清晰。您包含的查询时间戳仅相隔 6 毫秒,这可能并不能真正表明您正在尝试做什么。
  • 好多了。所以间隔总是均匀的?我的意思是例如分组中所有文档之间的 1 分钟?当然可以选择更改该间隔,但需要在分组结果之间保持一致的间隔。
  • @NeilLunn 是的,边界是固定的,比如 1 分钟

标签: mongodb mongodb-query aggregation-framework


【解决方案1】:

对于定期间隔,最好的办法是执行一些“日期数学”以将文档中的当前"timestamp" 值四舍五入为一个公共间隔值以进行分组。执行此操作的最佳方法是使用标准匹配减去应用于所需间隔的毫秒值的模数(余数)。

在我们提供的聚合框架中,使用$subtract$mod_id 键中$group@ 中的当前文档"unique" 字段值一起构成复合键的一方:

db.division_entry.aggregate([
  // Sanely restrict to a range of dates to analyse - here is one day
  { "$match": { 
    "timestamp": { "$gte": 1495670400000, "$lt": 1495756800000 }
  }},

  // Group by interval - example of 1 hour ( 1000ms * 60sec * 60min )
  { "$group": {
    "_id": {
      "time": {
        "$subtract": [
          "$timestamp",
          { "$mod": [ "$timestamp", ( 1000 * 60 * 60 ) ] }
        ]
      },
      "unique": "$unique"
    },
    "count": { "$sum": 1 }
  }}
])

因此,对于不同的间隔,您只需提供所需间隔的数学运算:

  • 1分钟(1000 * 60)
  • 1小时(1000 * 60 * 60)
  • 1天(1000*60*60*24)

仅供参考,有一个新引入的$bucket 运算符,但它的目的是用于统一的“切点”。即 0-5 分钟、6-20 分钟、20-50 分钟和超过 50 分钟作为示例用例。

对于任何“统一”的东西,基于数学的方法是最有效的实现方法。

【讨论】:

  • 如何在 Java 中实现 $subtract?官方文档提到只是自己构建文档,我正在寻找更基于代码/更快的解决方案
  • @MonsieurBeilto 这取决于实现。您始终可以Ask a New Question 或简单地搜索可能已经在这里的现有答案(我可能已经写了其中一些)。其核心是所有 BSON 基本上要么是 Document,要么是标准 Java List
【解决方案2】:

这是基于/启发自 Neil 的回答。

我还想要的是不同的时间间隔和其中唯一 uuid 的数量。他提供的答案给出了,对于每个唯一的 uuid,它在一个时间间隔内出现的次数,也就是在 q 中。

db.divisive_entry.aggregate([
  { "$match": { 
    "timestamp": { "$gte": 1395448852351, "$lt": 1497428775000 }
  }},

  { "$group": {
    "_id": {
      "time": {
        "$subtract": [
          "$timestamp",
          { "$mod": [ "$timestamp", ( 1000 * 60 * 60 ) ] }
        ]
      },
      "unique": "$unique"
    },
  }},

  { "$group": 
    {
        "_id": "$_id.time",
        "count" : { "$sum": 1 }
    }
  }
])

【讨论】:

  • 您本可以简单地留下评论来澄清这种差异,而您的问题中没有任何内容表明情况如此。这也不是“线程讨论”,而是一个问题和一个明确的答案。如果它是您想要的每个时间段的“不同唯一性计数”,那么第二个分组确实是这样做的方法。但是,下次您提出问题时,您应该发表评论以向回答的人澄清,而不是让他们呆在那里。
猜你喜欢
  • 1970-01-01
  • 2012-10-07
  • 1970-01-01
  • 1970-01-01
  • 2017-01-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多