mongodb - 在 Mongo 聚合中,可以通过分组生成 3 个不同的计数

标签 mongodb aggregate grouping

目前,我有 3 个不同的聚合查询,它们根据 companyRegNo 的分组生成不同的计数。有没有办法结合这 3 个查询。

employeeActions 数据如下所示:

{   
    "email": "<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="b4dbdad1f4d3d9d5ddd89ad7dbd9" rel="noreferrer noopener nofollow">[email protected]</a>",
    "companyRegNo" : 105,    
    "event" : {
        "created" : ISODate("2022-09-16T06:42:42.761Z"),
        "desc" : "COMPLETED_APPLICATIONS",
        "note" : "Direct apply",       
    }
}
{   
    "email": "<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="e08f8e85a0878d81898cce838f8d" rel="noreferrer noopener nofollow">[email protected]</a>",
    "companyRegNo" : 247,
    "event" : {
        "created" : ISODate("2022-09-16T06:42:04.387Z"),       
        "desc" : "COMPLETED_APPLICATIONS",
        "note" : "",       
    }
}
{   
    "email": "<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="e38c8d86a3848e828a8fcd808c8e" rel="noreferrer noopener nofollow">[email protected]</a>",
    "companyRegNo" : 247,    
    "event" : {
        "created" : ISODate("2022-09-16T06:42:42.761Z"),
        "desc" : "COMPLETED_REVIEW",
        "note" : ""Sent for review"",       
    }
}
{   
    "email": "<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="b0dfded5f0d7ddd1d9dc9ed3dfdd" rel="noreferrer noopener nofollow">[email protected]</a>",
    "companyRegNo" : 105,    
    "event" : {
        "created" : ISODate("2022-09-16T06:42:42.761Z"),
        "desc" : "COMPLETED_REVIEW",
        "note" : "Data is complete",       
    }
}
{   
    "email": "<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="d8b7b6bd98bfb5b9b1b4f6bbb7b5" rel="noreferrer noopener nofollow">[email protected]</a>",
    "companyRegNo" : 247,
    "event" : {
        "created" : ISODate("2022-09-16T06:42:04.387Z"),       
        "desc" : "COMPLETED_OFFER",
        "note" : "",       
    }
}
{   
    "email": "<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="eb84858eab8c868a8287c5888486" rel="noreferrer noopener nofollow">[email protected]</a>",
    "companyRegNo" : 227,
    "event" : {
        "created" : ISODate("2022-09-16T06:42:04.387Z"),       
        "desc" : "COMPLETED_APPLICATIONS",
        "note" : "",       
    }
}
{   
    "email": "<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="8ffbf8e0cfe8e2eee6e3a1ece0e2" rel="noreferrer noopener nofollow">[email protected]</a>",
    "companyRegNo" : 227,    
    "event" : {
        "created" : ISODate("2022-09-16T06:42:42.761Z"),
        "desc" : "COMPLETED_APPLICATIONS",
        "note" : "",       
    }
}

{   
    "email": "<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="b4c0c3dbf4d3d9d5ddd89ad7dbd9" rel="noreferrer noopener nofollow">[email protected]</a>",
    "companyRegNo" : 105,    
    "event" : {
        "created" : ISODate("2022-09-16T06:42:42.761Z"),
        "desc" : "COMPLETED_APPLICATIONS",
        "note" : "Direct apply",       
    }
}

这 3 个不同的查询是:

查询评论计数

db.getCollection('employeeActions').aggregate([
{"$match": { 
    "event.created": {"$gte": ISODate("2022-06-01 00:00:00.000Z")},
    "$or": [ {"event.desc": "COMPLETED_REVIEW"}, {"event.note": "Sent for review"}],
}},
{"$group":{"_id":"$companyRegNo","count": {"$sum": 1 } } },
{"$project":{ "companyRegNo":"$_id","count": "$count","_id":0}}
])

结果将是

105    1  
227    0  
247    1  

查询优惠计数

db.getCollection('employeeActions').aggregate([
{"$match": { 
    "event.created": {"$gte": ISODate("2022-06-01 00:00:00.000Z")},
    "event.desc": "COMPLETED_OFFER"
}},
{"$group":{"_id":"$companyRegNo","count": {"$sum": 1 } } },
{"$project":{ "companyRegNo":"$_id","count": "$count","_id":0}},
])

结果将是

105    0  
227    0  
247    1  

查询应用程序计数

db.getCollection('employeeActions').aggregate([
{"$match": { 
    "event.created": {"$gte": ISODate("2022-06-01 00:00:00.000Z")},
    "event.desc": "COMPLETED_APPLICATIONS"
}},
{"$group":{"_id":"$companyRegNo","count": {"$sum": 1 } } },
{"$project":{ "companyRegNo":"$_id","count": "$count","_id":0}},
])

结果将是

105    2
227    2
247    1

有没有办法组合这 3 个查询,以便得到如下结果?

CompanyRegNo 应用程序评论优惠

105            2           1         0
227            2           0         0
247            1           1         1

我尝试使用 $facet 来组合这些查询。它为我提供了所有公司的总计 3 个计数。

"offers" : 1, "reviews" : 2, "applications" : 5 

我需要将数据拆分到各个公司。

db.getCollection('employeeActions').aggregate([
    { "$match": { "event.created": {"$gte": ISODate("2022-01-01 00:00:00.000Z")}}},
    { "$facet": {                            
          "offers": [                           
            {"$match":{ "event.desc": "COMPLETED_OFFER" } },
            {"$group":{"_id":"$companyRegNo","count": {"$sum": 1 } } },
            { "$count": "offers" },
          ],
          "reviews": [                           
            {"$match":{ 
                "$or": [ {"event.desc": "COMPLETED_REVIEW"}, {"event.note": "Sent for review"}],
               }},
            {"$group":{"_id":"$companyRegNo","count": {"$sum": 1 }} },
            { "$count": "reviews" },
          ],
          "applications": [                           
            {"$match":{   "event.desc": "COMPLETED_APPLICATIONS" } },
            {"$group":{"_id":"$companyRegNo","count":{"$sum": 1 }} },
            { "$count": "applications" },
          ]    
       }
    },
    { "$project": {
        "offers": { "$arrayElemAt": ["$offers.offers", 0] },
        "reviews": { "$arrayElemAt": ["$reviews.reviews", 0] },
        "applications": { "$arrayElemAt": ["$applications.applications", 0] }
      }}
 ])```

最佳答案

虽然 @NeNaD 的答案被认为是“最佳实践”(我投票支持它),但由于 $facet 是针对此类情况创建的,因此重要的是要知道,还有其他选择。使用 $facet 也有缺点,其中之一是它将所有文档“合并”为一个大文档,并且文档有大小限制。如果您的集合很大,并且许多文档符合您的第一个条件,您可能需要考虑其他方法。

一种替代方法是将 $group$cond 一起使用:

db.collection.aggregate([
  {$match: {
      "event.created": {$gte: ISODate("2022-06-01T00:00:00.000Z")}
  }},
  {$group: {
      _id: "$companyRegNo",
      ReviewCount: {
        $sum: {$cond: [
            {$or: [
                {$eq: ["$event.desc", "COMPLETED_REVIEW"]},
                {$eq: ["$event.note", "Sent for review"]}
              ]
            }, 1, 0]}
      },
      OfferCount: {
        $sum: {$cond: [{$eq: ["$event.desc", "COMPLETED_OFFER"]}, 1, 0]}
      },
      ApplicationsCount: {
        $sum: {$cond: [{$eq: ["$event.desc", "COMPLETED_APPLICATIONS"]}, 1, 0]}
      }
    }
  }
])

看看它在 playground example 上的工作原理

关于mongodb - 在 Mongo 聚合中,可以通过分组生成 3 个不同的计数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73818175/

相关文章:

database - Zsh:找不到命令:mongo 在尝试使用 brew 安装 mongodb 4.2 之后

mongodb - 连接到远程 mongoDB 服务器

python - Pandas:计算列中的一些值

python - pandas groupby 并聚合两列以获得各自的总数,然后计算比率 - 总结摘要

python - 在这个算法中使用计数排序有什么好处?

javascript - 对象数组到按属性分组的对象数组

java - 找不到 mongoTemplate bean

python - 如何对 Pandas 中的两个领域进行分组?

matlab - matlab中矩阵中的分组元素

mongodb - 在 mongoDB 中执行联合