MongoDB 聚合框架:按两个字段分组

5

我正在使用聚合和管道查询我的数据库,需要进行两个单独的查询:

 $groups_q = array(
            '$group' => array(
                '_id' => '$group_name',
                'total_sum' => array('$sum' => 1)
                )
            );

  $statuses_q = array(
            '$group' => array(
                '_id' => '$user_status',
                'total_sum' => array('$sum' => 1)
                )
            );

$data['statuses'] = $this->mongo_db->aggregate('users',$statuses_q);
$data['groups'] = $this->mongo_db->aggregate('users',$groups_q);

我得到了我想要的:

Array
(
[statuses] => Array
    (
        [result] => Array
            (
                [0] => Array
                    (
                        [_id] => Inactive
                        [total_sum] => 2
                    )

                [1] => Array
                    (
                        [_id] => Active
                        [total_sum] => 5
                    )

            )

        [ok] => 1
    )

[groups] => Array
    (
        [result] => Array
            (
                [0] => Array
                    (
                        [_id] => Accounting 
                        [total_sum] => 1
                    )

                [1] => Array
                    (
                        [_id] => Administrator
                        [total_sum] => 2
                    )

                [2] => Array
                    (
                        [_id] => Rep
                        [total_sum] => 1
                    )
            )

        [ok] => 1
    )

)

我不想两次查询我的数据库。有没有更好的方法来完成它?我该如何用一次查询来实现?我应该使用$project操作符吗?


你在查询两个不同的集合吗?你能再解释一下你想做什么吗? - Jeff Storey
我正在查询同一集合,并按两个不同的字段(状态和组名)进行分组。我试图获得与我提供的相同结果,即按组合并按状态分开,但在一个查询中。 - Sergey Tsibel
我认为这将需要两个查询。 - Jeff Storey
1个回答

13

使用单个aggregate()无法以所需的结果格式执行两个分组计数。一旦数据被第一次分组,您就不再具有创建第二个计数所需的细节。

直截了当的方法是执行两个查询,就像你已经做的那样 ;-).

其他选择的想法

如果您真的想在一个聚合查询中获得信息,您可以在两个字段上进行分组,然后在应用程序代码中进行一些操作。带有两个字段的组_id将产生每个group_name和status的组合结果。

示例使用mongo shell:

db.users.aggregate(
    { $group: {
         _id: { group_name: "$group_name", status: "$status" },
         'total_sum': { $sum: 1 }
    }}
)

这种方法似乎并不特别高效,会导致应用代码变得复杂,因为你需要对结果进行两次迭代才能获得预期的分组。

如果你只想要每个组中唯一的名称而不是名称+计数,你可以在单个组中使用$addToSet

另一个明显的选择是在应用程序代码中进行分组。进行单个find(),仅投影group_namestatus字段,并在迭代结果时建立计数数组。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接