聚合时间序列数据
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 查询和过滤功能来执行此操作的方法,想寻求建议:
- 我在单个文档中存储多个指标的方法是否合理?我是否最好将指标保存为单独的文档,然后以某种方式 "merging" 它们?
- 有没有一种方法可以在不使用 nodejs 的情况下实现我需要的功能(我认为这不会很快 - 获取文档然后迭代它们以创建一个新结构并将其推出) ?
- 有更好的方法吗?虚拟模型或猫鼬中的东西可以提供帮助吗?我知道 mongoDB 可能不是时间序列数据的正确选择,但它不是功能的唯一部分, mongoDB/mongoose 组合似乎很好地服务于其他目的,我不想改变技术中途。
是的,但请记住,文档的大小有限 (16 MB IIRC),因此如果您的数据是无界的,此结构将无法工作,因为您的 "metrics" 数组会增长过去了。
最终是的,即使你想不出合适的过滤器查询,Mongo 有 MapReduce 可以让你做你想做的事,虽然这并不容易.我会为此使用 Node。
这里没有灵丹妙药。如果您需要聚合数据并将其存储为任意 JSON(即由应用程序使用),Mongo 非常好,但不擅长处理复杂的 joins/views 数据。应用程序级别的任何连接都会很慢。如果你想要性能,你必须将你的报告聚合到单独的文档中,并保存并提供它们。如果您有实时数据,这将更加困难,因为您需要处理更新。
我正在使用 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 查询和过滤功能来执行此操作的方法,想寻求建议:
- 我在单个文档中存储多个指标的方法是否合理?我是否最好将指标保存为单独的文档,然后以某种方式 "merging" 它们?
- 有没有一种方法可以在不使用 nodejs 的情况下实现我需要的功能(我认为这不会很快 - 获取文档然后迭代它们以创建一个新结构并将其推出) ?
- 有更好的方法吗?虚拟模型或猫鼬中的东西可以提供帮助吗?我知道 mongoDB 可能不是时间序列数据的正确选择,但它不是功能的唯一部分, mongoDB/mongoose 组合似乎很好地服务于其他目的,我不想改变技术中途。
是的,但请记住,文档的大小有限 (16 MB IIRC),因此如果您的数据是无界的,此结构将无法工作,因为您的 "metrics" 数组会增长过去了。
最终是的,即使你想不出合适的过滤器查询,Mongo 有 MapReduce 可以让你做你想做的事,虽然这并不容易.我会为此使用 Node。
这里没有灵丹妙药。如果您需要聚合数据并将其存储为任意 JSON(即由应用程序使用),Mongo 非常好,但不擅长处理复杂的 joins/views 数据。应用程序级别的任何连接都会很慢。如果你想要性能,你必须将你的报告聚合到单独的文档中,并保存并提供它们。如果您有实时数据,这将更加困难,因为您需要处理更新。