mongodb - MongoDb聚合 - 滑动窗口平均值?
问题描述
我正在尝试使用 mongodb 聚合框架来平均每学期每分钟最后一小时的“分数”。我当然没有按分钟分组的问题..只是不清楚按分钟分组的最佳方式,但然后让 mongo 每分钟返回一个小时来计算平均分数。在这里搜索并找到一些选项后,我觉得 $bucket 由于性能原因并不是最好的方法,map/reduce 也是如此。所以只是在寻找意见。我不需要经常运行此查询,因为我通常每分钟都会在我的应用程序中执行此运行计算.. 但需要首先根据我收集的原始数据“播种”数据,
样本原始文件:
{
"_id" : ObjectId("603e472aba52820ab3e139ae"),
"term" : "sports",
"created_at" : ISODate("2021-03-02T14:09:46.701Z"),
"score" : -0.331166666666667,
},
{
"_id" : ObjectId("6031272aba52820ab3e139ef"),
"term" : "sports",
"created_at" : ISODate("2021-03-02T14:09:55.000Z"),
"score" : 1.05
},
{
"_id" : ObjectId("io12iopeipweipqeqweqwewq"),
"term" : "food",
"created_at" : ISODate("2021-03-10T16:02:12.091Z"),
"score" : 0.25,
}
我想要一个类似于的结果集
term | for minute "x" | average of scores from (x - 1 hour) to x
------------------------------------------------------------------------------------
sports | 03/31/2021 14:10:00 | (average of all "sports" scores from 3/31/2021 13:10:00 to 3/31/2021 14:10:00)
food | 03/31/2021 14:10:00 | (average of all "food" scores from 3/31/2021 13:10:00 to 3/31/2021 14:10:00)
sports | 03/31/2021 14:11:00 | (average of all "sports" scores from 3/31/2021 13:11:00 to 3/31/2021 14:11:00)
预先感谢您提供任何可能愿意提供的建议!
解决方案
试试这个:
db.collection.aggregate([
{
$group: {
_id: "$term",
min_created: { $min: "$created_at" },
data: { $push: "$$ROOT" }
}
},
{
$project: {
score: {
$map: {
input: { // generate sequence of 60 Minutes
$map: {
input: { $range: [0, 60] },
in: { $add: ["$min_created", { $multiply: ["$$this", 60, 1000] }] }
}
},
as: "ts",
in: {
range_start: "$$ts",
range_end: { $add: ["$$ts", 1000 * 60 * 60] },
scores: {
$filter: { // select data fitting in range
input: "$data",
cond: {
$and: [
{ $gte: ["$$this.created_at", "$$ts"] },
{ $lt: ["$$this.created_at", { $add: ["$$ts", 1000 * 60 * 60] }] }
]
}
}
}
}
}
}
}
},
{ // make average score
$set: {
score: {
$map: {
input: "$score",
as: "score",
in: {
range_start: "$$score.range_start",
range_end: "$$score.range_end",
score: { $avg: "$$score.scores.score" }
}
}
}
}
},
{ // suppress empty ranges
$set: {
score: {
$filter: {
input: "$score",
cond: { $ne: ["$$this.score", null] }
}
}
}
}
])
您没有提供所需的输出(作为 JSON),所以我只能猜测。您可能需要做一些外观上的改变。我希望原则应该清楚。
您可以将某些阶段合并为一个阶段。但是,我将它们分开以获得更好的可见性。
$map
应该比 工作得更好$reduce
,请参阅https://jira.mongodb.org/browse/SERVER-53503
推荐阅读
- sql-server - SQL MERGE 代替 INSERT - 优化
- r - 在 ggplot 中使用 stat_density_2d 的求和因子的密度图
- ios - 在 ContainerView 内的 UICollectionView 中计算单元格宽度
- c# - Monogame 中的小行星克隆生成具有相同位置、旋转和方向的小行星
- php - 来自定义的应用程序访问的 Bitnami 应用程序插入查询
- html - 避免浏览器打印出现空白页
- jquery - jQuery 选择器在 Gmail 中的 COMPOSE 下方添加按钮
- vue.js - vue.js - 更新时关闭模式
- python - 正则表达式 (Python) - 匹配具有两个或多个不同元音的单词
- java - 如何正确地从数组中获取索引并对其进行一些操作?