mongodb中的时间序列数据 - 如何查询嵌入文档

时间:2015-03-02 15:31:27

标签: mongodb time-series

我正在研究时间序列数据集的设计,基本上我有我监控的服务器,我想知道一段时间内它的一些指标。 基于http://blog.mongodb.org/post/65517193370/schema-design-for-time-series-data-in-mongodb 我创建了一个设计,每个服务器+月份的文档,每天一个嵌入式文档,每小时一个嵌入式文档,其中包含度量标准。

所以为某个服务器插入两个小时的数据如下所示:

- 对于服务器i-09484d47和日期2015/02/23小时16

db.servers.update(
  { _id : "i-09484d47_201502",
    service: "AWS/EC2",
    owner : "gil"
  }, 
  {$set: {"values.23.16.samples": 60 ,"values.23.16.average": 0.33883, "values.23.16.minimum": 0.16, "values.23.16.maximum": 0.67} },
  { upsert: true }
)

- 对于服务器i-09484d47和日期2015/02/23小时17

db.servers.update(
  { _id : "i-09484d47_201502",
    service: "AWS/EC2",
    owner : "gil"
  }, 
  {$set: {"values.23.17.samples": 60 ,"values.23.17.average": 0.6, "values.23.17.minimum": 0.5, "values.23.17.maximum": 0.8} },
  { upsert: true }
)

等等。

现在我想得到特定服务器的所有数据,对于给定的日期范围,比如某一周(让我们说它包含在一个月内)。 我不想拉整个文档并在客户端上进行过滤。 任何想法?

1 个答案:

答案 0 :(得分:2)

由于您在按键中指定时间和日期,可以通过投影要显示的按键来完成此操作。所以,如果您想要2月16日至22日这一周,您可以这样做:

db.servers.find(
    { "_id": "i-09484d47_201502" },
    {
        "values.16": 1,
        "values.17": 1,
        "values.18": 1,
        "values.19": 1,
        "values.20": 1,
        "values.21": 1,
        "values.22": 1
    }
);

您可以看到手动输入是多么痛苦,因此您可能希望使用在给定一系列日期的情况下返回投影对象的函数。在同一个月内,在JavaScript中,它可以像这样工作:

function generateProjection(start, end) {

    obj = {};
    prefix = "values";

    for (var i = start; i <= end; i++) {
        var key = prefix + "." + i;
        obj[key] = 1;
    }

    return obj;
}

然后您可以按如下方式使用:

var proj = generateProjection(16, 22);
db.servers.find({ "_id": "i-09484d47_201502" }, proj);

如果您愿意,只需稍加变化,就可以添加多个月和几小时的支持。替代方法是更改​​您的架构,以便将有关日期的信息包含为值,并可能将每个子文档存储在一个数组中,以便您可以利用$unwind中的aggregation运算符

PS。有点偏离主题,但鉴于_id是唯一的,您不需要在更新查询中指定所有匹配条件。您可以将其简化为以下内容:

修改 添加了$setOnInsert子句以涵盖upsert所需的字段。

db.servers.update(
  { "_id": "i-09484d47_201502" }, 
  { "$set": { ... },
  { "$setOnInsert": { "service": "AWS/EC2", "owner": "gil" } },
  { "upsert": true }
);