【问题标题】:Mongodb Aggregate - Grouping by hour for todayMongodb 聚合 - 今天按小时分组
【发布时间】:2020-05-04 22:47:49
【问题描述】:

我想知道是否有人可以帮助我正确设置聚合函数。我正在尝试计算我的健身访问量。我有访问表,其中保存了每次访问(从,到)日期。还保存了对某些服务的子访问。

[{
  "from": ISODate("2020-01-17T10:23:27.645Z"),
  "to": ISODate("2020-01-17T12:23:28.760Z"),
  "visits": [
    {
      "from": ISODate("2020-01-17T10:23:27.646Z"),
      "to": ISODate("2020-01-17T10:30:28.760Z"),
      "service": ObjectId("5e05f17d6b7f7920d4a62403")
    },
    {
      "from": ISODate("2020-01-17T10:30:29.760Z"),
      "to": ISODate("2020-01-17T12:23:28.760Z"),
      "service": ObjectId("5d05f17dt57f7920d4a62404")
    }
  ],
  ...
},
{
  "from": ISODate("2020-01-17T10:40:00.000Z"),
  "to": ISODate("2020-01-17T11:30:28.760Z"),
  "visits": [
    {
      "from": ISODate("2020-01-17T10:40:00.000Z"),
      "to": ISODate("2020-01-17T11:30:28.760Z"),
      "service": ObjectId("h505f17s6b2f7920d4a6295y")
    }
  ],
  ...
}
]

如果当前时间是 13:35,我想从 00:00 获得今天的结果,然后一直到 13:00,例如:

[{
  'date': '2020-01-18T00:00:0.000Z'
  'visits': 0
},
{
  'date': '2020-01-18T00:00:0.000Z'
  'visits': 0
},
{
  'date': '2020-01-18T00:00:0.000Z'
  'visits': 0
},
{
  'date': '2020-01-18T01:00:0.000Z'
  'visits': 0
},
{
  'date': '2020-01-18T02:00:0.000Z'
  'visits': 0
},
{
  'date': '2020-01-18T03:00:0.000Z'
  'visits': 0
},
{
  'date': '2020-01-18T04:00:0.000Z'
  'visits': 0
},
{
  'date': '2020-01-18T05:00:0.000Z'
  'visits': 0
},
{
  'date': '2020-01-18T06:00:0.000Z'
  'visits': 0
},
{
  'date': '2020-01-18T07:00:0.000Z'
  'visits': 0
},
{
  'date': '2020-01-18T08:00:0.000Z'
  'visits': 0
},
{
  'date': '2020-01-18T09:00:0.000Z'
  'visits': 0
},
{
  'date': '2020-01-18T010:00:0.000Z'
  'visits': 2
},
{
  'date': '2020-01-18T11:00:0.000Z'
  'visits': 2
},
{
  'date': '2020-01-18T12:00:0.000Z'
  'visits': 1
},
{
  'date': '2020-01-18T13:00:0.000Z'
  'visits': 0
}]

尝试了太多示例,但没有任何效果,请帮助!

【问题讨论】:

    标签: javascript mongodb mongoose aggregation-framework


    【解决方案1】:

    解释

    1. 如果我们使用$$NOW,我们会得到当前日期。如果您手动设置currDatetodaynextDay,MongoDB 聚合将限制所需的值。

    2. 现在,我们计算从today (yyyy-MM-dd 00:00:00) - currDate (yyyy-MM-dd 13:35:00) ~ 13 小时和$range运算符创建数组

    3. 我们展平区间并应用过滤

    你可以使用这样的查询:

    db.collection.aggregate([
      {
        $addFields: {
          nextDay: {
            $add: [
              {
                $dateFromString: {
                  dateString: {
                    $substr: [
                      {
                        $toString: "$$NOW"
                      },
                      0,
                      10
                    ]
                  },
                  format: "%Y-%m-%d"
                }
              },
              {
                $multiply: [
                  24,
                  60,
                  60,
                  1000
                ]
              }
            ]
          },
          today: {
            $dateFromString: {
              dateString: {
                $substr: [
                  {
                    $toString: "$$NOW"
                  },
                  0,
                  10
                ]
              },
              format: "%Y-%m-%d"
            }
          },
          currDate: {
            $dateFromString: {
              dateString: {
                $substr: [
                  {
                    $toString: "$$NOW"
                  },
                  0,
                  13
                ]
              },
              format: "%Y-%m-%dT%H",
              timezone: "-01"
            }
          }
        }
      },
      {
        $addFields: {
          interval: {
            $range: [
              0,
              {
                $add: [
                  {
                    $divide: [
                      {
                        $subtract: [
                          "$currDate",
                          "$today"
                        ]
                      },
                      {
                        $multiply: [
                          60,
                          60,
                          1000
                        ]
                      }
                    ]
                  },
                  1
                ]
              },
              1
            ]
          }
        }
      },
      {
        $unwind: "$interval"
      },
      {
        $addFields: {
          date: {
            $add: [
              "$today",
              {
                $multiply: [
                  "$interval",
                  60,
                  60,
                  1000
                ]
              }
            ]
          },
          nextHour: {
            $add: [
              "$today",
              {
                $multiply: [
                  {
                    $add: [
                      "$interval",
                      1
                    ]
                  },
                  60,
                  60,
                  1000
                ]
              }
            ]
          }
        }
      },
      {
        $project: {
          _id: 0,
          date: 1,
          today: 1,
          nextDay: 1,
          visits: {
            $reduce: {
              input: "$visits",
              initialValue: 0,
              in: {
                $add: [
                  "$$value",
                  {
                    $cond: [
                      {
                        $or: [
                          {
                            $and: [
                              {
                                $gte: [
                                  "$$this.from",
                                  "$date"
                                ]
                              },
                              {
                                $lte: [
                                  "$$this.from",
                                  "$nextHour"
                                ]
                              }
                            ]
                          },
                          {
                            $and: [
                              {
                                $lte: [
                                  "$date",
                                  "$$this.to"
                                ]
                              },
                              {
                                $gte: [
                                  "$date",
                                  "$$this.from"
                                ]
                              }
                            ]
                          }
                        ]
                      },
                      1,
                      0
                    ]
                  }
                ]
              }
            }
          }
        }
      },
      {
        $match: {
          $expr: {
            $and: [
              {
                $gte: [
                  "$date",
                  "$today"
                ]
              },
              {
                $lte: [
                  "$date",
                  "$nextDay"
                ]
              },
    
            ]
          }
        }
      },
      {
        $group: {
          _id: "$date",
          visits: {
            $sum: "$visits"
          }
        }
      },
      {
        $sort: {
          _id: 1
        }
      }
    ])
    

    MongoPlayground

    JS设置,点击here

    如果你想要更优雅的方式,你可以尝试this 解决方案

    【讨论】:

    • 我们可以使用 JavaScript 变量中的 startDate 和 endDate 吗?
    • 当然。设置 currDatenextDaytoday
    • 确保您复制粘贴了我的代码的最新版本
    • 好的,谢谢你帮助我。现在我有最后一个问题,它正在承受我的健身负担。就像我的访问时间是从 10:00 到 12:30,我需要显示在 10:00 访问 1 次,在 11:00 访问 1 次,并且在 12:00 还访问 1 次。我怎样才能达到这个逻辑?
    猜你喜欢
    • 2014-08-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-28
    • 2021-05-19
    • 2013-11-25
    • 2016-07-03
    相关资源
    最近更新 更多