【问题标题】:Can the field names in a MongoDB document be queried, perhaps using aggregation?可以查询 MongoDB 文档中的字段名称,也许使用聚合?
【发布时间】:2013-11-15 11:00:46
【问题描述】:

在这篇来自 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 和最高字段名称)?

非常感谢!

【问题讨论】:

  • 我可能建议您始终将值加倍存储,如果这是您想要执行的常见查询:"most_recent_value"

标签: mongodb time-series aggregation-framework


【解决方案1】:

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

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

【讨论】:

    【解决方案2】:

    我在另一篇博客文章中找到了“可以查询字段名称”的答案,该文章显示仅在 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
        }
    }
    

    还有map reduce函数:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-11-03
      • 1970-01-01
      • 2014-10-10
      • 2020-08-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多