MongoDB、时间序列和聚合框架

Posted

技术标签:

【中文标题】MongoDB、时间序列和聚合框架【英文标题】:MongoDB, TimeSeries and Aggregation Framework 【发布时间】:2015-10-24 20:54:39 【问题描述】:

所以,我正在使用 MongoDB 处理这个时间序列数据并发现: http://blog.mongodb.org/post/65517193370/schema-design-for-time-series-data-in-mongodb

它说这种结构不会利用“文档模型的表达性”:


  timestamp: ISODate("2013-10-10T23:06:37.000Z"),
  type: ”memory_used”,
  value: 1000000

他们建议像这样(分钟/秒):


  timestamp_hour: ISODate("2013-10-10T23:00:00.000Z"),
  type: “memory_used”,
  values: 
    0:  0: 999999, 1: 999999, …, 59: 1000000 ,
    1:  0: 2000000, 1: 2000000, …, 59: 1000000 ,
    …,
  

所以我决定像这样(年/月)对我的数据进行建模:


  "unity_of_measure": "MWh",
  "region": "North",
  "consumption": 
    2014: 1: 2568.652, 2: 2614.621, 3: 2711.012  ,
    2015: 1: 2751.234, 2: 2752.231, 3: 2752.215  ,
    …
  

我不知道我是不是搞错了,但是聚合框架似乎无法获得最大/最小/总和/平均值,例如,使用这种建模。

所以我把我的模型改成了这样:


  "unity_of_measure": "MWh",
  "region": "North",
  "consumption": [
     "year": 2014,
      "month": 1,
      "value": 2568.652
    ,
     "year": 2014,
      "month": 2,
      "value": 2614.621
    
    ...
  ]

但现在我发现自己没有利用“文档模型的表达性”。所以我真的很困惑。

有没有什么方法可以使用聚合框架和 mongo 的博客建议的建模?这里的想法是不使用 map reduce 或类似的东西。

如果不可能,第二次建模在性能方面有多糟糕?

抱歉这个问题太长了,我希望我能在这里贴一个土豆。

提前致谢。

【问题讨论】:

不要太拘泥于“文档模型的表达性”——我认为这是文章中的不幸措辞。他们提出的模式只是一种有助于满足设计目标的选择。它因其他设计目标而失败,如下所述。六年前,我在 Oracle 中编写了完全相同的策略,而 mongo 设计不再具有表现力——它们在功能上是等效的,并且具有相似的表现力。 你好史蒂夫塔弗。非常感谢您与我和社区分享的所有信息和经验,它确实帮助我考虑了很多事情!如果你知道一些文章或任何讨论这个话题的东西,你能和我分享吗?再次感谢! 哪个主题?大规模指标收集或列表计算? 【参考方案1】:

我认为您错过了文章中的一些重要内容 -> 他们会在每次更新时更新汇总统计字段,以便他们可以计算应用程序中的平均值。他们在时间序列数据上使用 $set,在 num_samples 和 total_samples 上使用 $inc,因为文档字段更新非常便宜并且允许它们达到它们所处的规模。时间序列数据用于显示 - 不用于 mongo 中的计算。

聚合和映射函数对列表进行操作 - 您的第一个示例没有 - 它有一个包含时间序列数据的子文档。您可以在聚合管道中进行平均,但在应用程序代码中这样做会非常难看且更简单。

如果您想在 mongo 中进行计算,则必须将数据组织在某种列表中,例如您的第二个示例。

使用第二个模式作为提示,您可以按照以下方式进行计算。打开一个 mongo shell,使用一个像 test 一样的临时数据库,然后将其粘贴进去看看它是否工作。

// clean up from previous run
db.timeSeries2.drop();

// Given data like
db.timeSeries2.insert(
    
      "unit_of_measure": "MWh",
      "region": "North",
      "consumption": [
        
          "year": 2014,
          "month": 1,
          "value": 50
        ,
        
          "year": 2014,
          "month": 2,
          "value": 100
        ,
        
          "year": 2014,
          "month": 3,
          "value": 150
        ,
        
          "year": 2015,
          "month": 1,
          "value": 500
        ,
        
          "year": 2015,
          "month": 2,
          "value": 1000
        ,
        
          "year": 2015,
          "month": 3,
          "value": 1500
        
      ]
    
);

// aggregation to provide min/max/sum/average
db.timeSeries2.aggregate([
  $match: region: 'North', unit_of_measure: 'MWh',
  $unwind: '$consumption',
  $match: 'consumption.year': 2014,
  
    $group: 
      _id: 'summary',
      avg: $avg: '$consumption.value',
      sum: $sum: '$consumption.value',
      min: $min: '$consumption.value',
      max: $max: '$consumption.value'
    
  
])

生产


  "result": [
    
      "_id": "summary",
      "avg": 100,
      "sum": 300,
      "min": 50,
      "max": 150
    
  ],
  "ok": 1

【讨论】:

以上是关于MongoDB、时间序列和聚合框架的主要内容,如果未能解决你的问题,请参考以下文章

Mongodb解释聚合框架

使用 MongoDB 聚合框架计算一阶导数

在 MongoDB 聚合框架中计算中位数

在 mongodb 聚合框架中展开字典值

MongoDB 聚合框架匹配或

使用聚合框架使用 MongoDB 进行组计数