Mongo Aggregation : $group and $project array to object for counts

前端 未结 1 1036
忘了有多久
忘了有多久 2020-12-04 03:23

I have documents like:

{
    \"platform\":\"android\",
    \"install_date\":20151029
}
  1. platform - can have one value from [android|io
相关标签:
1条回答
  • 2020-12-04 03:57

    With MongoDb 3.4 and newer, you can leverage the use of $arrayToObject operator to get the desired result. You would need to run the following aggregate pipeline:

    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 } } 
    ])
    

    For older versions, take advantage of the $cond operator in the $group pipeline step to evaluate the counts based on the platform field value, something like the following:

    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"
            }
        } }
    ])
    

    In the above, $cond takes a logical condition as it's first argument (if) and then returns the second argument where the evaluation is true (then) or the third argument where false (else). This makes true/false returns into 1 and 0 to feed to $sum respectively.

    So for example, if { "$eq": [ "$platform", "facebook" ] }, is true then the expression will evaluate to { $sum: 1 } else it will be { $sum: 0 }

    0 讨论(0)
提交回复
热议问题