是否可以使用聚合查询MongoDB文档中的字段名称?

时间:2013-11-04 18:14:18

标签: mongodb time-series aggregation-framework

在MongoDB博客的这篇文章中," Schema Design for Time Series Data in MongoDB"作者建议将多个时间序列值存储在单个文档中,作为基本时间戳的编号子项(即每分钟的文档,以值为数组的秒数)。

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

建议的架构听起来不错,但是他们没有提到如何查询"值"如果您想知道最后一个样本何时发生,则需要使用字段名称。

您将如何构建查询以查找最新指标的时间(在值中组合timestamp_minute和最高字段名称)?

非常感谢!

2 个答案:

答案 0 :(得分: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

答案 1 :(得分:0)

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

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

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

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")
}