【问题标题】:MongoDB complex aggregationMongoDB复杂聚合
【发布时间】:2019-11-04 04:38:23
【问题描述】:

我的数据库中有以下结构的文档:

{
    "reading_ts": ISODate(...),
    "points": 2.3,
    "user_id": 2
}

对于每个 user_id,我每天都会有更多这样的文档……数以百万计…… 我想实现以下聚合:

  1. 获取一个月的数据
  2. 为每个 user_id 分组数据
  3. 对每一天的数据进行分组(这样我就有了每一天的数据,对于每个 user_id)
  4. 获取每个用户每天的最大“积分”
  5. 统计有多少用户的最大点数低于 10,有多少在 10 到 20 之间,有多少超过 20

我可以使用 $match 完成第 1 步 我可以使用这个来完成第 3 步:

{
    "$group": {
        "_id": {
            "$subtract": [
                "$reading_ts",
                {
                    "$mod": [
                        {
                            "$toLong": "$reading_ts"
                        },
                        (1000 * 60 * 60 * 24)
                    ]
                }
            ]
        }
    }
}

问题是我现在不知道如何合并步骤 2 和 3。

【问题讨论】:

    标签: mongodb aggregate


    【解决方案1】:

    您可以使用$dayOfMonth$max 在一个$group 阶段将步骤2、3 和4 结合起来,以获得每个用户每天的最大“积分”。

    然后,您可以使用$bucket 运算符将用户数按桶计数,边界设置为 [0, 10, 20]:

    db.collection.aggregate([
      {
        "$match": {
          "reading_ts": {
            "$gte": ISODate("2019-01-01"),
            "$lte": ISODate("2019-01-30")
          }
        }
      },
      {
        "$group": {
          "_id": {
            "user": "$user_id",
            "day": {
              "$dayOfMonth": "$reading_ts"
            }
          },
          "max": {
            "$max": "$points"
          }
        }
      },
      {
        "$bucket": {
          "groupBy": "$max",
          "boundaries": [
            0,
            10,
            20
          ],
          "default": 20,
          "output": {
            "users": {
              "$sum": 1
            },
    
          }
        }
      }
    ])
    

    在线试用:mongoplayground.net/p/jzZdz2V7R4-

    【讨论】:

    • 谢谢! $dayOfMonth 是一个好方法,但问题是我实际上有最近 30 天的 $match 过滤器,而不是月份。这是我的描述不好:)
    猜你喜欢
    • 2014-10-21
    • 2018-10-31
    • 1970-01-01
    • 2021-03-09
    • 1970-01-01
    • 1970-01-01
    • 2014-03-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多