Mongo Aggregation:$ group和$ project数组来计算对象

时间:2015-10-29 11:43:44

标签: mongodb aggregation-framework

我有以下文件:

{
    "platform":"android",
    "install_date":20151029
}
  1. 平台 - 可以从[android | ios | kindle | facebook]中获得一个值。
  2. install_date - 有很多install_dates
  3. 还有很多领域。

    目标:我在特定日期计算每个平台的安装量。

    所以我在聚合框架中使用group by并按平台进行计数。文档应如下所示:

    {
      "install_date":20151029,
      "platform" : {
       "android":1000,
       "ios": 2000,
       "facebook":1500
      }
    }
    

    我做过:

    db.collection.aggregate([
      { 
          $group: { 
              _id: { platform: "$platform",install_date:"$install_date"},  
                count: { "$sum": 1 } 
            }
      },
      { 
          $group: { 
              _id: { install_date:"$_id.install_date"},
              platform: { $push :  {platform :"$_id.platform", count:"$count" } }  
          }
      },
      { 
         $project : { _id: 0, install_date: "$_id.install_date", platform: 1 } 
      }     
    ]) 
    

    给出如下文件:

    {
        "platform": [
            {
                "platform": "facebook",
                "count": 1500
            },
            {
                "platform": "ios",
                "count": 2000
            },
            {
                "platform": "android",
                "count": 1000
            }
        ],
        "install_date": 20151027
    }
    

    问题:

    将数组投影到单个对象作为" platform"

1 个答案:

答案 0 :(得分:1)

使用MongoDb 3.4及更新版本,您可以利用$arrayToObject运算符来获得所需的结果。您需要运行以下聚合管道:

db.collection.aggregate([
    { "$group": {
        "_id": {  
            "date": "$install_date",  
            "platform": { "$toLower": "$platform" }
        },
        "count": { "$sum": 1 }
    } },
    { "$group": {
        "_id": "$_id.date",
        "counts": {
            "$push": {
                "k": "$_id.platform",
                "v": "$count"
            }
        }
    } },
    {  "$addFields": {
        "install_date": "$_id", 
        "platform": { "$arrayToObject": "$counts" }
    }  },
    { "$project": { "counts": 0, "_id": 0 } } 
])

对于旧版本,请利用$cond管道步骤中的$group运算符,根据平台字段值评估计数,如下所示:

db.collection.aggregate([    
    { "$group": { 
        "_id": "$install_date",             
        "android_count": {
            "$sum": {
                "$cond": [ { "$eq": [ "$platform", "android" ] }, 1, 0 ]
            }
        },
        "ios_count": {
            "$sum": {
                "$cond": [ { "$eq": [ "$platform", "ios" ] }, 1, 0 ]
            }
        },
        "facebook_count": {
            "$sum": {
                "$cond": [ { "$eq": [ "$platform", "facebook" ] }, 1, 0 ]
            }
        },
        "kindle_count": {
            "$sum": {
                "$cond": [ { "$eq": [ "$platform", "kindle" ] }, 1, 0 ]
            }
        } 
    } },
    { "$project": {
        "_id": 0, "install_date": "$_id",            
        "platform": {
            "android": "$android_count",
            "ios": "$ios_count",
            "facebook": "$facebook_count",
            "kindle": "$kindle_count"
        }
    } }
])

在上面,$cond采用逻辑条件作为它的第一个参数(if)然后返回第二个参数,其中评估为真(然后)或第三个参数,其中false(else) 。这使得返回1和0的真/假分别馈送到$sum

例如,如果{ "$eq": [ "$platform", "facebook" ] },为真,那么表达式将评估为{ $sum: 1 },否则它将为{ $sum: 0 }