mongoDB 时间戳聚合 nodejs mongoose

mongoDB timestamp aggregation nodejs mongoose

我已经搜索了一段时间,并没有真正找到足够明确的答案来理解如何去做。 我将图表数据保存在 MongoDB 中,以分钟为基准(Unix 时间戳)。现在我明白了,如果我想以每小时或每天为基础可视化图表,我需要聚合数据,但我并不完全理解需要做什么。

我想创建 1 小时和 1 天的组,这些组需要包含其时间范围的最后一条记录。然后聚合是否需要完成一次并保存到数据库?或者每次我查询它。以及如何在 mongoose 中设置查询?

这里是我收集的图表数据的例子

collection:[
{
 time: 1649083392,
 volume: '20384.28',
 open: 444.42,
 close: 444.56,
 high: 444.76,
 low: 444.36
},
{
 time: 1649083448,
 volume: '20384.28',
 open: 444.42,
 close: 444.56,
 high: 444.76,
 low: 444.36
},
{
 time: 1649083501,
 volume: '20384.28',
 open: 444.42,
 close: 444.56,
 high: 444.76,
 low: 444.36
}
]

假设我需要一个每天时间表的图表。一天有1440分钟

我首先需要每天做一个组来累加每天的体积,然后投影每天的最后一个项目。它应该预测每天的数量和每天的最后一项。

希望有人能向我解释一下这是如何工作的。谢谢

----更新---

对不起。所以我弄错了。

[{
  "pairAddress": "0x58F876857a02D6762E0101bb5C46A8c1ED44Dc16",
  "chart": [
    {
      "time": 1648978488,
      "high": "442.93181339228767",
      "low": "440.89881857342505",
      "open": "440.89901371910537",
      "close": "442.9168809785855",
      "marketcap": "2505922284.61",
      "volume": "14264.118014884118",
      "_id": {
        "$oid": "62496a3b8741c95e7661a0c2"
      }
    },
    {
      "time": 1648978536,
      "high": "442.9603776582797",
      "low": "442.9122490168528",
      "open": "442.9292814855807",
      "close": "442.9478700257827",
      "marketcap": "2506097613.54",
      "volume": "19482.73456302384",
      "_id": {
        "$oid": "62496a778741c95e7661a971"
      }
    },
    {
      "time": 1648978608,
      "high": "442.9893218041529",
      "low": "442.941310936878",
      "open": "442.9481594715175",
      "close": "442.9893218041529",
      "marketcap": "2506332138.21",
      "volume": "16138.024513587941",
      "_id": {
        "$oid": "62496ab38741c95e7661b53a"
      }
    },
    {
      "time": 1648978668,
      "high": "443.5010551781398",
      "low": "442.9032561370158",
      "open": "442.9893789835573",
      "close": "443.5010551781398",
      "marketcap": "2509227408.46",
      "volume": "24664.532500429723",
      "_id": {
        "$oid": "62496aef8741c95e7661c000"
      }
    },
    {
      "time": 1648978728,
      "high": "443.5205214040826",
      "low": "443.4918353053875",
      "open": "443.50216033083433",
      "close": "443.5202071089899",
      "marketcap": "2509335765.70",
      "volume": "5548.645723580672",
      "_id": {
        "$oid": "62496b2b8741c95e7661c951"
      }
    },
    {
      "time": 1648978788,
      "high": "443.6375372213781",
      "low": "443.470378539243",
      "open": "443.50698654937736",
      "close": "443.5999403093497",
      "marketcap": "2509786877.88",
      "volume": "52212.176474500986",
      "_id": {
        "$oid": "62496b678741c95e7661d396"
      }
    },
    {
      "time": 1648978848,
      "high": "443.61143763713756",
      "low": "443.58718500668306",
      "open": "443.59987943714646",
      "close": "443.5872533304441",
      "marketcap": "2509715097.86",
      "volume": "14691.325842608467",
      "_id": {
        "$oid": "62496ba38741c95e7661e2d3"
      }
    }
  ]
}]

这是我文档的实际示例,我需要在图表数组上进行聚合。使用现有代码我无法让它工作。

db.collection.aggregate([
  {
    $sort: { time: -1 }
  },
  {
    $set: {
      d: { $toDate: { $multiply: [ "$time", 1000 ] } },
      volume: { $toDecimal: "$volume" }
    }
  },
  {
    $facet: {
      day: [
        {
          $group: {
            _id: {
              $dateTrunc: {
                date: "$d",
                unit: "day"
              }
            },
            volume: { $sum: "$volume" },
            lastItem: { $first: "$$ROOT" }
          }
        }
      ],
      hour: [
        {
          $group: {
            _id: {
              year: { $year: "$d" },
              dayOfYear: { $dayOfYear: "$d" },
              hour: { $hour: "$d" }
            },
            volume: { $sum: "$volume" },
            lastItem: { $first: "$$ROOT" }
          }
        }
      ],
      15min: [
        {
          $group: {
            _id: {
              year: { $year: "$d" },
              dayOfYear: { $dayOfYear: "$d" },
              hour: { $hour: "$d" },
              interval: {
                $subtract: [
                  { $minute: "$d" },
                  { $mod: [ { $minute: "$d" }, 15 ] }
                ]
              }
            },
            volume: { $sum: "$volume" },
            lastItem: { $first: "$$ROOT" }
          }
        }
      ]
    }
  }
])

mongoplayground

我知道这已经得到解答,但我的做法是将时间戳设置为间隔,然后根据时间戳边界对数据进行分组

db.data.aggregate([
    {
        $addFields: {
            // Your Group Interval In Seconds eg.
            // - 86400 For Per Day
            // - 3600 Per Hour
            // - 900 Per 15 minute
            timestampBoundary: {
                $subtract: ["$time", {$mod: ["$time", 3600]}]
            },
        }
    },
    {
        $sort: {
            time: -1
        }
    },
    {
        $group: {
            _id: "$timestampBoundary",
            lastItem: {$first: "$$ROOT"},
            totalVolume: {
                $sum: {
                    $toDecimal: "$volume"
                }
            },
        }
    }
])

所以,我对此仍有疑问,因为需要聚合的数据位于文档数组中。

我找到了 $unwind 函数来解决这个问题。

Chart.aggregate([
  {$match:{"pairAddress": "0x58F876857a02D6762E0101bb5C46A8c1ED44Dc16"}},
  {$unwind: "$chart"},
  {$addFields: {
       timestampBoundary: {$subtract: ["$chart.time",{$mod: ["$chart.time", 900]}]},
  }},
  {$sort: {"chart.time": -1}},
  {$group: {
      _id: "$timestampBoundary",
      lastItem: {$first: "$$ROOT"},
      volume: {$sum: {$toDecimal: "$chart.volume"}}
  }},
  {$sort:{ _id: 1}}
])

首先我使用 $match 来确保我只得到我想要聚合的文档, 展开我要聚合的图表数组。然后添加一个新字段将 UNIX 时间戳转换为按时间戳排序。之后我可以按时间戳排序并制作 一组指定的时间间隔。将每组的体积相加并进行最后排序。在 $mod: 900 代表秒,这是我可以指定组的时间间隔的地方。

感谢@YuTing 和@Calvin Coomer 我现在得到了完美的解决方案。