relacionados - Conteo de grupo con MongoDB usando el marco de agregación
mongodb documentos relacionados (2)
Digamos que mi esquema de MongoDB se ve así:
{car_id: "...", owner_id: "..."}
Esta es una relación de muchos a muchos. Por ejemplo, los datos pueden verse así:
+-----+----------+--------+
| _id | owner_id | car_id |
+-----+----------+--------+
| 1 | 1 | 1 |
| 2 | 1 | 2 |
| 3 | 1 | 3 |
| 4 | 2 | 1 |
| 5 | 2 | 2 |
| 6 | 3 | 4 |
| 7 | 3 | 5 |
| 8 | 3 | 6 |
| 9 | 3 | 7 |
| 10 | 1 | 1 | <-- not unique
+-----+----------+--------+
Quiero obtener la cantidad de autos que posee cada propietario. En SQL, esto podría verse así:
SELECT owner_id, COUNT(*) AS cars_owned
FROM (SELECT owner_id FROM car_owners GROUP BY owner_id, car_id) AS t
GROUP BY owner_id;
En este caso, el resultado se vería así:
+----------+------------+
| owner_id | cars_owned |
+----------+------------+
| 1 | 3 |
| 2 | 2 |
| 3 | 4 |
+----------+------------+
¿Cómo puedo lograr esto mismo usando MongoDB usando el marco de agregación?
Para acomodar los posibles duplicados, necesita usar dos operaciones $group
:
db.test.aggregate([
{ $group: {
_id: { owner_id: ''$owner_id'', car_id: ''$car_id'' }
}},
{ $group: {
_id: ''$_id.owner_id'',
cars_owned: { $sum: 1 }
}},
{ $project: {
_id: 0,
owner_id: ''$_id'',
cars_owned: 1
}}]
, function(err, result){
console.log(result);
}
);
Da un resultado con un formato de:
[ { cars_owned: 2, owner_id: 10 },
{ cars_owned: 1, owner_id: 11 } ]
$group
es similar al comando SQL Group by. En el siguiente ejemplo, agregaremos compañías en función del año en que se fundaron. Y calcule el número promedio de empleados para cada compañía.
db.companies.aggregate([{
$group: {
_id: {
founded_year: "$founded_year"
},
average_number_of_employees: {
$avg: "$number_of_employees"
}
}
}, {
$sort: {
average_number_of_employees: -1
}
}
])
Esta tubería de agregación tiene 2 etapas
-
$group
-
$sort
Ahora, fundamental para la etapa $group
es el campo _id
que especificamos como la parte del documento. Ese es el valor del operador de $group
mismo utilizando una interpretación muy estricta de la sintaxis del marco de arrogación. _id
es cómo definimos, cómo controlamos, cómo sintonizamos lo que la etapa grupal usa para organizar los documentos que ve.
La siguiente consulta encuentra las relaciones de las personas con empresas que usan el operador $sum
:
db.companies.aggregate([{
$match: {
"relationships.person": {
$ne: null
}
}
}, {
$project: {
relationships: 1,
_id: 0
}
}, {
$unwind: "$relationships"
}, {
$group: {
_id: "$relationships.person",
count: {
$sum: 1
}
}
}, {
$sort: {
count: -1
}
}])