0

在 MongoDB 博客的这篇文章“MongoDB中时间序列数据的模式设计”中,作者建议将多个时间序列值存储在单个文档中,作为基本时间戳的编号子项(即文档每分钟,秒作为值数组)。

{
  timestamp_minute: ISODate("2013-10-10T23:06:00.000Z"),
  type: “memory_used”,
  values: {
    0: 999999,
    …  
    37: 1000000,
    38: 1500000,
    … 
    59: 2000000
  }
}

提议的模式听起来不错,但他们没有提到如何查询“值”字段名称,如果您想知道最后一个样本发生的时间,则需要这些名称。

您将如何构建查询以查找最近度量的时间(结合值中的 timestamp_minute 和最高字段名称)?

非常感谢!

4

2 回答 2

0

您可以只查询分钟文档,然后在客户端上使用循环来确定已设置哪些时间戳:

doc = c.find(...)
var last = 0
for (var i=0; i<60; i++)
    if (i in doc.values)
        last = i

另一种更有效的方法是使用数组而不是文档来存储每秒样本,然后使用数组的长度来确定存储了多少秒样本:

doc = c.find(...)
last = doc.values.length - 1
于 2013-11-04T18:41:44.510 回答
0

我在另一篇博客文章中找到了“可以查询字段名称”的答案,该文章显示了仅在 MapReduce 函数 ala 中对键进行迭代(如 Bruce 建议的那样):

  var d = 0;
  for (var key in this.values)
      d = Math.max(d, parseInt(key));

对于 MMS 示例架构(在下面标记为 v 的值数组中以月份交换 timestamp_minute 和天),这里是生成最新度量日期的数据和查询:

db.metricdata.find();

/* 0 */
{
    "_id" : ObjectId("5277e223be9974e8415f66f6"),
    "month" : ISODate("2013-10-01T04:00:00.000Z"),
    "type" : "ga-pv",
    "v" : {
        "10" : 57,
        "11" : 49,
        "12" : 91,
        "13" : 27,
      ...
    }
}

/* 1 */
{
    "_id" : ObjectId("5277e223be9974e8415f66f7"),
    "month" : ISODate("2013-11-01T04:00:00.000Z"),
    "type" : "ga-pv",
    "v" : {
        "1" : 145,
        "2" : 51,
        "3" : 63,
        "4" : 29
    }
}

和地图减少功能:

db.metricdata.mapReduce(
    function() {
        var y = this.month.getFullYear();
        var m = this.month.getMonth();
        var d = 0;

        // Here is where the field names used
        for (var key in this.v)
            d = Math.max(d, parseInt(key));

        emit(this._id, new Date(y,m,d));
    },
    function(key, val)
    {
        return null;
    },
    {out: "idandlastday"}
 ).find().sort({ value:-1}).limit(1)

这会产生类似

/* 0 */
{
    "_id" : ObjectId("5277e223be9974e8415f66f7"),
    "value" : ISODate("2013-11-04T05:00:00.000Z")
}
于 2013-11-04T21:55:29.347 回答