如何在MongoDB中使用嵌套分组

时间:2016-09-17 20:17:54

标签: mongodb mongodb-query aggregation-framework mongodb-aggregation

我需要找到每个组织级别的重复配置文件总数。我有如下文件:

{
    "OrganizationId" : 10,
    "Profile" : {
        "_id" : "75"
    }
    "_id" : "1"
},
{
    "OrganizationId" : 10,
    "Profile" : {
        "_id" : "75"
    }
    "_id" : "2"
},
{
    "OrganizationId" : 10,
    "Profile" : {
        "_id" : "77"
    }
    "_id" : "3"
},
{
    "OrganizationId" : 10,
    "Profile" : {
        "_id" : "77"
    }
    "_id" : "4"
}

我编写的查询是ProfileId和OrganizationId的一个组。我得到的结果如下所示:

Organization    Total
10               2
10               2

但我希望获得每个组织级别的总和,这意味着组织10应该有一行,总和为4.

我正在使用的查询如下所示:

 db.getSiblingDB("dbName").OrgProfile.aggregate(
 { $project: { _id: 1, P: "$Profile._id",  O: "$OrganizationId" } },
 { $group: {_id: { p: "$P", o: "$O"}, c: { $sum: 1 }} },
 { $match: { c: { $gt: 1 } } });

有什么想法吗?请帮忙

2 个答案:

答案 0 :(得分:2)

以下管道应该为您提供所需的输出,而最后$project阶段仅用于美化目的,将_id转换为OrganizationId,但基本计算不需要,所以你可以省略它。

db.getCollection('yourCollection').aggregate([
    { 
        $group: {  
            _id: { org: "$OrganizationId", profile: "$Profile._id" },
            count: { $sum: 1 }
        }
    },
    {
        $group: {
            _id: "$_id.org",
            Total: { 
                $sum: { 
                    $cond: { 
                        if: { $gte: ["$count", 2] }, 
                        then: "$count", 
                        else: 0
                    }
                }
            }
        } 
     },
     {
         $project: {
             _id: 0,
             Organization: "$_id",
             Total: 1
         }
     }
])

给出了这个输出

{
    "Total" : 4.0,
    "Organization" : 10
}

要过滤掉没有重复项的组织,您可以使用$match,这也可以简化第二个$group阶段

...aggregate([
    { 
        $group: {  
            _id: { org: "$OrganizationId", profile: "$Profile._id" },
            count: { $sum: 1 }
        }
    },
    {
        $match: {
            count: { $gte: 2 } 
        }
    },
    {
        $group: {
            _id: "$_id.org",
            Total: { $sum: "$count" }
        } 
     },
     {
         $project: {
             _id: 0,
             Organization: "$_id",
             Total: 1
         }
     }
])

答案 1 :(得分:0)

我想我有一个解决方案。在那最后一步,而不是匹配,我想你想要另一个$group

    .aggregate([

     { $project: { _id: 1, P: "$Profile._id",  O: "$OrganizationId" } }
     ,{ $group: {_id: { p: "$P", o: "$O"}, c: { $sum: 1 }} }
     ,{ $group: { _id: "$_id.o" , c: {  $sum: "$c" } }}

     ]);

你可以阅读它并自己弄清楚最后一步发生了什么,但万一我会解释。最后一步是对具有相同组织ID的所有文档进行分组,然后对前一个c字段指定的数量求和。在第一组之后,您有两个文件,其计数c为2,但配置文件ID不同。下一组会忽略配置文件ID,只要它们具有相同的组织ID并将其计数添加,即可将它们分组。

当我运行此查询时,这是我的结果,这是我认为您正在寻找的内容:

{
    "_id" : 10,
    "c" : 4
}

希望这会有所帮助。如果您有任何问题,请告诉我。