如何在 MongoDB 中使用嵌套分组

How to use nested grouping in MongoDB

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

{
    "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

但我想获得每个组织级别的总和,这意味着 Org 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 } } });

有什么想法吗?请帮助

我想我有一个解决方案。在最后一步,我想你想要另一个 $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
}

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

下面的管道应该给你想要的输出,而最后的 $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
         }
     }
])