Я запрашиваю мою базу данных, используя агрегацию и конвейер, с двумя отдельными запросами:
$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 operator?
Вы не можете использовать один aggregate()
для выполнения двух сгруппированных счетчиков с желаемым форматом результата. После того, как данные были сгруппированы в первый раз, у вас больше нет деталей, необходимых для создания второго счета.
Прямым подходом является выполнение двух запросов, как вы уже делаете ;-).
Если вы действительно хотите получить информацию в одном агрегированном запросе, вы можете группировать оба поля, а затем выполнять некоторые манипуляции в коде приложения. С двумя полями в группе _id
результаты будут представлять собой каждую комбинацию group_name и status.
Пример использования оболочки mongo
:
db.users.aggregate( { $group: { _id: { group_name: "$group_name", status: "$status" }, 'total_sum': { $sum: 1 } }} )
Это не кажется особенно эффективным и поддается некоторому запутанному прикладному коду, потому что вы должны дважды повторять результаты, чтобы получить ожидаемые группировки.
Если вам нужны только уникальные имена для каждой группы вместо имен + $addToSet
, вы можете использовать $addToSet
в одной группе.
Другой очевидной альтернативой было бы сделать группировку в вашем коде приложения. Сделайте одиночную find()
проецирующую только group_name
и status
, и создайте свои массивы count, когда вы повторяете результаты.