首页 > 解决方案 > 如何在Mongo中获取特定日期每小时的平均值?

问题描述

我在 MongoDB 中有一个集合,我想获得value给定一天 24 小时时间间隔的平均值。

这是我的收藏:

[
  {
    "_id": 1,
    "value": 50,
    "created_at": 1614217700
  },
  {
    "_id": 2,
    "value": 60,
    "created_at": 1614219300
  },
  {
    "_id": 3,
    "value": 100,
    "created_at": 1614226200
  },
  {
    "_id": 4,
    "value": 80,
    "created_at": 1614227400
  }
]

文档 3 和 4 位于同一时间段,因此 80 和 100 的平均值为 90。这是我期望的结果示例(或类似结果)。

[
    {
      "time": 0,
      "avg_value": null
    },
    {
      "time": 1,
      "avg_value": 50
    },
    {
      "time": 2,
      "avg_value": 60
    },
    {
      "time": 3,
      "avg_value": null
    },
    {
      "time": 4,
      "avg_value": 90
    },
    ,
    ,
    ,
    {
      "time": 23,
      "avg_value": null
    }
  ]

在这里你可以找到我的例子:https ://mongoplayground.net/p/YaAeebapbD-

任何想法将不胜感激。谢谢!

标签: mongodbaggregation-framework

解决方案


数据库中可能有可用时间,对于空值,您需要准备静态数组并与结果合并,

  • $multiply created_at用 1000 将其转换为毫秒
  • $toDate将毫秒数转换为 ISO 日期
  • $hour获取小时表 ISO 日期
  • $group按高于转换和平均value使用的小时$avg
let result = db.collection.aggregate([
  {
    "$match": {
      "created_at": {
        "$gte": 1614211200,
        "$lt": 1614297599
      }
    }
  },
  {
    $group: {
      _id: { $hour: { $toDate: { $multiply: ["$created_at", 1000] } } },
      avg_value: { $avg: "$value" }
    }
  }
])

操场

结果将是,

[
    { "_id": 1, "avg_value": 50 },
    { "_id": 2, "avg_value": 60 },
    { "_id": 4, "avg_value": 90 }
]

合并空闲时间并导致客户端,如果您使用的是 Javascript / NodeJs,您可以查看示例,

// RESULT FROM QUERY
let result = [
    { "_id": 1, "avg_value": 50 },
    { "_id": 2, "avg_value": 60 },
    { "_id": 4, "avg_value": 90 }
];

// GENERATE NULL HOURS FOR 23 HOURS IN ARRAY
let hours = [];
for (let i = 0; i<24; i++) hours.push({ _id: i, avg_value: null });

// MERGE WITH QUERY RESULT
let mergeArray = hours.map(h => {
    let f = result.find(r => h._id === r._id);
    return f ? f : h;
});

console.log(mergeArray);


推荐阅读