在同一个mongodb查询中选择按计数和不同计数分组

Posted

技术标签:

【中文标题】在同一个mongodb查询中选择按计数和不同计数分组【英文标题】:Select Group by count and distinct count in same mongodb query 【发布时间】:2014-09-05 19:54:24 【问题描述】:

我正在尝试做类似的事情

select campaign_id,campaign_name,count(subscriber_id),count(distinct subscriber_id)
group by campaign_id,campaign_name from campaigns;

这个查询给出的结果除了 count(distinctsubscriber_id)

db.campaigns.aggregate([
    $match: subscriber_id: $ne: null,
    $group:  
        _id: campaign_id: "$campaign_id",campaign_name: "$campaign_name",
        count: $sum: 1
    
])

以下查询给出的结果除了 count(subscriber_id)

db.campaigns_logs.aggregate([
    $match : subscriber_id: $ne: null,
    $group :  _id: campaign_id: "$campaign_id",campaign_name: "$campaign_name",subscriber_id: "$subscriber_id",
    $group :  _id: campaign_id: "$campaign_id",campaign_name: "$campaign_name", 
                count: $sum: 1
              
])

但我希望 count(subscriber_id),count(distinctsubscriber_id) 在相同的结果中

【问题讨论】:

【参考方案1】:

当你朝着正确的方向前进时,你开始沿着正确的路线思考。改变你的 SQL 思维方式,“distinct”实际上只是用任何一种语言编写$group 操作的另一种方式。这意味着您有两个组操作在这里发生,并且在聚合管道术语中,两个管道阶段。

只需用简化的文档来可视化:


    "campaign_id": "A",
    "campaign_name": "A",
    "subscriber_id": "123"
,

    "campaign_id": "A",
    "campaign_name": "A",
    "subscriber_id": "123"
,

    "campaign_id": "A",
    "campaign_name": "A",
    "subscriber_id": "456"

按理说,对于给定的“广告系列”组合,总计数和“不同”计数分别为“3”和“2”。因此,合乎逻辑的做法是首先将所有这些“subscriber_id”值“分组”并保持每个值的出现次数,然后在考虑“管道”时,“总计”每个“活动”的这些计数,然后只计算“ distinct" 出现为单独的数字:

db.campaigns.aggregate([
     "$match":  "subscriber_id":  "$ne": null ,

    // Count all occurrences
     "$group": 
        "_id": 
            "campaign_id": "$campaign_id",
            "campaign_name": "$campaign_name",
            "subscriber_id": "$subscriber_id"
        ,
        "count":  "$sum": 1 
    ,

    // Sum all occurrences and count distinct
     "$group": 
        "_id": 
            "campaign_id": "$_id.campaign_id",
            "campaign_name": "$_id.campaign_name"
        ,
        "totalCount":  "$sum": "$count" ,
        "distinctCount":  "$sum": 1 
    
])

在第一个“组”之后,输出文档可以这样可视化:

 
    "_id" :  
        "campaign_id" : "A", 
        "campaign_name" : "A", 
        "subscriber_id" : "456"
    , 
    "count" : 1 

 
    "_id" :  
        "campaign_id" : "A", 
        "campaign_name" : "A", 
        "subscriber_id" : "123"
    , 
    "count" : 2

因此,从样本中的“三个”文档中,“2”属于一个不同的值,而“1”属于另一个。这仍然可以与$sum 相加,以获得您在下一个阶段所做的全部匹配文档,以及最终结果:

 
    "_id" :  
        "campaign_id" : "A", 
        "campaign_name" : "A"
    ,
    "totalCount" : 3,
    "distinctCount" : 2

聚合管道的一个很好的类比是 unix 管道“|”运算符,它允许“链接”操作,因此您可以将一个命令的输出传递到下一个命令的输入,依此类推。开始以这种方式考虑您的处理需求将帮助您更好地了解聚合管道的操作。

【讨论】:

是的,我使用聚合有一段时间了,直到现在才理解它。我只是完全避免了管道的管道方面的复杂性,因为 mongoDB 的文档在这方面非常混乱,需要你的例子!【参考方案2】:

SQL 查询:(分组方式和不同的计数)

select city,count(distinct(emailId)) from TransactionDetails group by city;

等效的 mongo 查询如下所示:

db.TransactionDetails.aggregate([ 
$group:_id:"CITY" : "$cityName",uniqueCount: $addToSet: "$emailId",
$project:"CITY":1,uniqueCustomerCount:$size:"$uniqueCount"  
]);

【讨论】:

以上是关于在同一个mongodb查询中选择按计数和不同计数分组的主要内容,如果未能解决你的问题,请参考以下文章

如何按范围分组,或有条件地从查询结果中选择

MongoDB聚合组和计数字符串

MongoDB计数按数组元素分组的数组中的匹配字符串

从子查询存储过程分配变量

按时间范围确定的每月计数

在一个查询中按计数和运算符获取结果