MongoDB,时间序列和聚合框架

MongoDB, TimeSeries and Aggregation Framework

所以,我正在使用 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
}

他们提出了这样的建议 (minutes/second):

{
  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 },
    …,
  }
}

所以我决定像这样对我的数据建模,(year/month):

{
  "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 } ,
    …
  }
}

我不知道我是否弄错了,但聚合框架似乎无法获得 max/min/sum/avg 值,例如,使用这种建模。

所以我把模型改成这样:

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

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

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

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

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

提前致谢。

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

中的计算

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

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

使用第二个模式作为提示,下面是您如何进行计算。打开一个 mongo shell,使用类似测试的临时数据库,并将其粘贴进去以查看它是否有效。

// 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
}