【问题标题】:How to group date quarterly wise?如何明智地按季度分组日期?
【发布时间】:2015-04-02 04:42:17
【问题描述】:

我有包含日期​​的文档,我想知道如何按季度对它们进行分组?

我的架构是:

var ekgsanswermodel = new mongoose.Schema({
    userId: {type: Schema.Types.ObjectId},
    topicId : {type: Schema.Types.ObjectId},
    ekgId : {type: Schema.Types.ObjectId},
    answerSubmitted :{type: Number},
    dateAttempted : { type: Date},
    title : {type: String},
    submissionSessionId : {type: String}  
});

第 1 季度包含第 1、2、3 个月。第 2 季度包含第 4、5、6 个月等等,直到第 4 季度。

我的最终结果应该是:

 "result" : [ 
   {
     _id: {
        quater:
     },
     _id: {
        quater:
     },
    _id: {
        quater:
     },
     _id: {
        quater:
     }
  }

【问题讨论】:

  • 你试过使用 MongoDB 的 mapreduce 吗? docs.mongodb.org/manual/core/map-reduce 我想你可以用四舍五入的 MonthNumber/4 来映射你的月份。像emit(this.number/4,this.number)这样的东西。在 REDUCE 部分,您将所有月份分组。
  • 我没有尝试过mapreduce。可以给我一个例子。我也在上面添加了架构。
  • 别介意我的解决方案@grishabh,下面的那个更好。 Mongodb mapreduce 不允许您将数组作为 reduce 操作的结果。参考:stackoverflow.com/questions/8175015/…

标签: mongodb date mongoose mongodb-query quarter


【解决方案1】:

Mongo 5 开始,这是新的$dateTrunc 聚合运算符的完美用例:

// { date: ISODate("2012-10-11") }
// { date: ISODate("2013-02-27") }
// { date: ISODate("2013-01-12") }
// { date: ISODate("2013-03-11") }
// { date: ISODate("2013-07-14") }
db.collection.aggregate([
  { $group: {
    _id: { $dateTrunc: { date: "$date", unit: "quarter" } },
    total: { $count: {} }
  }}
])
// { _id: ISODate("2012-10-01"), total: 1 }
// { _id: ISODate("2013-01-01"), total: 3 }
// { _id: ISODate("2013-07-01"), total: 1 }

$dateTruncquarter 的开头截断您的日期(截断unit)。这有点像每季度的日期模数。

输出中的季度将由第一天定义(Q3 2013 将是2013-07-01)。例如,您始终可以使用 $dateToString 投影对其进行调整。

【讨论】:

    【解决方案2】:

    您可以使用$cond 运算符来检查:

    • $month<= 3,投影一个名为quarter 的字段 值为“一”。
    • $month<= 6,投影一个名为quarter 的字段 值为“二”。
    • $month<= 9,投影一个名为quarter 的字段 值为“三”。
    • 否则字段quarter 的值为“第四”。
    • 然后是$group quarter 字段。

    代码:

    db.collection.aggregate([
      {
        $project: {
          date: 1,
          quarter: {
            $cond: [
              { $lte: [{ $month: "$date" }, 3] },
              "first",
              {
                $cond: [
                  { $lte: [{ $month: "$date" }, 6] },
                  "second",
                  {
                    $cond: [{ $lte: [{ $month: "$date" }, 9] }, "third", "fourth"],
                  },
                ],
              },
            ],
          },
        },
      },
      { $group: { _id: { quarter: "$quarter" }, results: { $push: "$date" } } },
    ]);
    

    特定于您的架构:

    db.collection.aggregate([
      {
        $project: {
          dateAttempted: 1,
          userId: 1,
          topicId: 1,
          ekgId: 1,
          title: 1,
          quarter: {
            $cond: [
              { $lte: [{ $month: "$dateAttempted" }, 3] },
              "first",
              {
                $cond: [
                  { $lte: [{ $month: "$dateAttempted" }, 6] },
                  "second",
                  {
                    $cond: [
                      { $lte: [{ $month: "$dateAttempted" }, 9] },
                      "third",
                      "fourth",
                    ],
                  },
                ],
              },
            ],
          },
        },
      },
      { $group: { _id: { quarter: "$quarter" }, results: { $push: "$$ROOT" } } },
    ]);
    

    【讨论】:

    • thanx @BatScream,请您在 spring-data-mongodb 中进行此查询。
    【解决方案3】:

    您可以使用以下功能按季度对文档进行分组。

    {
        $project : {
            dateAttempted : 1,
            dateQuarter: {
                $trunc : {$add: [{$divide: [{$subtract: [{$month: 
                "$dateAttempted"}, 1]}, 3]}, 1]}
            }
        }
    }
    

    【讨论】:

    • 如果可能的话,我喜欢简短的。谢谢。
    猜你喜欢
    • 1970-01-01
    • 2015-07-22
    • 1970-01-01
    • 2014-12-28
    • 2012-10-19
    • 1970-01-01
    • 2023-01-18
    • 1970-01-01
    • 2021-03-15
    相关资源
    最近更新 更多