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

time series data in mongodb - how to query embedded document

我正在设计一个时间序列数据集,基本上我有我监控的服务器,我想知道一段时间内关于它的一些指标。 基于 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 }
)

等等。

现在我想获取特定服务器的所有数据,在给定的日期范围内,比如说某个星期(假设它包含在一个月内)。 我不想提取整个文档并在客户端上进行过滤。 有什么想法吗?

由于您在按键中指定了时间和日期,因此您可以通过投影要显示的按键来实现。所以如果你想要从 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
    }
);

您可以看到手动输入是多么痛苦,因此您可能希望使用 returns 给定日期范围的投影对象的函数。在同一个月内,在 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 }
);