我正在使用聚合和管道查询我的数据库,有两个单独的查询:
$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
)
)
我不想查询数据库两次。有更好的方法吗?我如何用一个查询完成它?我应该使用$项目操作符吗?
您不能使用单个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_name
和status
字段,并在迭代结果时构建计数数组。