聚合时间序列数据

Aggregate time series data

我正在使用 mongoDB 和 mongoose 来存储指标数据。它存储为一组指标的文档,这些指标引用为其存储的项目和指标类型。

此架构如下所示:

exports.metricReportSchema = new Schema({
    metrics: [{
        metric: {
            type: mongoose.Schema.Types.ObjectId,
            ref: 'metricSchema',
            required: true
        },
        value: {
            type: String,
            required: true
        }
    }],
    project: {
        type: mongoose.Schema.Types.ObjectId,
        ref: 'projectSchema',
        required: true
    },
    reportDate: Date
});

实际文档如下所示:

db.metricreports.findOne() {
    "_id" : ObjectId("58a60e8459dd3d12ef8c5d51"),
    "reportDate" : ISODate("2017-02-16T20:41:40.657Z"),
    "project" : ObjectId("58a20f5f04ef5789d3ef8faa"),
    "metrics" : [
        {
            "metric" : ObjectId("58a20f5f04ef5789d3ef8fb7"),
            "value" : "781",
            "_id" : ObjectId("58a60e8459dd3d12ef8c5d52")
        }, {
            "metric" : ObjectId("58a21106fc2aef8a10ded196"),
            "value" : "566",
            "_id" : ObjectId("58a60e8459dd3d12ef8c5d53")
        }, {
            "metric" : ObjectId("58a2141bded78e8ad8384f97"),
            "value" : "501",
            "_id" : ObjectId("58a60e8459dd3d12ef8c5d54")
        }, {
            "metric" : ObjectId("58a2141bded78e8ad8384f94"),
            "value" : "44",
            "_id" : ObjectId("58a60e8459dd3d12ef8c5d55")
        }, {
            "metric" : ObjectId("58a2141bded78e8ad8384f93"),
            "value" : "645",
            "_id" : ObjectId("58a60e8459dd3d12ef8c5d56")
        }
    ],
    "__v" : 0
}

随着时间的推移,有多个此类文档存储多个指标的数据片段。选择和显示多个项目的指标静态报告等非常方便。

现在,当我尝试为项目的单个指标构建时间序列报告时,这变得不那么复杂了。

基本上,我需要做的是扫描多个 metricReport 文档,并随着时间的推移从所有可用报告中提取单个指标的数据。假设我有 10 个 metricReports,每个包含 10 个不同指标的数据,我只想提取一个,这可能看起来像这样:

{
    "_id": "...",
    "project": "...",
    "metric": "...",
    "data": {
        "2016-02-02": "22",
        "2016-02-03": "453",
        ...
    }
}

我找不到使用开箱即用的 mongoDB 查询和过滤功能来执行此操作的方法,想寻求建议:

  1. 我在单个文档中存储多个指标的方法是否合理?我是否最好将指标保存为单独的文档,然后以某种方式 "merging" 它们?
  2. 有没有一种方法可以在不使用 nodejs 的情况下实现我需要的功能(我认为这不会很快 - 获取文档然后迭代它们以创建一个新结构并将其推出) ?
  3. 有更好的方法吗?虚拟模型或猫鼬中的东西可以提供帮助吗?我知道 mongoDB 可能不是时间序列数据的正确选择,但它不是功能的唯一部分, mongoDB/mongoose 组合似乎很好地服务于其他目的,我不想改变技术中途。
  1. 是的,但请记住,文档的大小有限 (16 MB IIRC),因此如果您的数据是无界的,此结构将无法工作,因为您的 "metrics" 数组会增长过去了。

  2. 最终是的,即使你想不出合适的过滤器查询,Mongo 有 MapReduce 可以让你做你想做的事,虽然这并不容易.我会为此使用 Node。

  3. 这里没有灵丹妙药。如果您需要聚合数据并将其存储为任意 JSON(即由应用程序使用),Mongo 非常好,但不擅长处理复杂的 joins/views 数据。应用程序级别的任何连接都会很慢。如果你想要性能,你必须将你的报告聚合到单独的文档中,并保存并提供它们。如果您有实时数据,这将更加困难,因为您需要处理更新。