MongoDB
Agregación
Buscar..
Introducción
Aggregations
operaciones de Aggregations
procesan registros de datos y devuelven resultados calculados. Las operaciones de agregación agrupan los valores de varios documentos y pueden realizar una variedad de operaciones en los datos agrupados para devolver un solo resultado. MongoDB proporciona tres formas de realizar la agregación: el canal de agregación, la función de reducción de mapas y los métodos de agregación de propósito único.
Del manual de Mongo https://docs.mongodb.com/manual/aggregation/
Sintaxis
- db.collection.aggregate (canalización, opciones)
Parámetros
Parámetro | Detalles |
---|---|
tubería | matriz (una secuencia de operaciones o etapas de agregación de datos) |
opciones | documento (opcional, disponible solo si la canalización está presente como una matriz) |
Observaciones
El marco de agregación en MongoDB se utiliza para lograr la funcionalidad común de GROUP BY
de SQL.
Considere las siguientes inserciones en la colección con nombre de transactions
para cada ejemplo.
> db.transactions.insert({ cr_dr : "D", amount : 100, fee : 2});
> db.transactions.insert({ cr_dr : "C", amount : 100, fee : 2});
> db.transactions.insert({ cr_dr : "C", amount : 10, fee : 2});
> db.transactions.insert({ cr_dr : "D", amount : 100, fee : 4});
> db.transactions.insert({ cr_dr : "D", amount : 10, fee : 2});
> db.transactions.insert({ cr_dr : "C", amount : 10, fee : 4});
> db.transactions.insert({ cr_dr : "D", amount : 100, fee : 2});
Contar
¿Cómo se obtiene el número de transacciones de débito y crédito? Una forma de hacerlo es utilizando la función count()
como se muestra a continuación.
> db.transactions.count({cr_dr : "D"});
o
> db.transactions.find({cr_dr : "D"}).length();
Pero qué cr_dr
si no conoce los posibles valores de cr_dr
upfront. Aquí el marco de agregación viene a jugar. Consulte la siguiente consulta de agregados.
> db.transactions.aggregate(
[
{
$group : {
_id : '$cr_dr', // group by type of transaction
// Add 1 for each document to the count for this type of transaction
count : {$sum : 1}
}
}
]
);
Y el resultado es
{
"_id" : "C",
"count" : 3
}
{
"_id" : "D",
"count" : 5
}
Suma
¿Cómo obtener la suma de amount
? Vea la siguiente consulta agregada.
> db.transactions.aggregate(
[
{
$group : {
_id : '$cr_dr',
count : {$sum : 1}, //counts the number
totalAmount : {$sum : '$amount'} //sums the amount
}
}
]
);
Y el resultado es
{
"_id" : "C",
"count" : 3.0,
"totalAmount" : 120.0
}
{
"_id" : "D",
"count" : 5.0,
"totalAmount" : 410.0
}
Otra versión que suma amount
y fee
.
> db.transactions.aggregate(
[
{
$group : {
_id : '$cr_dr',
count : {$sum : 1},
totalAmount : {$sum : { $sum : ['$amount', '$fee']}}
}
}
]
);
Y el resultado es
{
"_id" : "C",
"count" : 3.0,
"totalAmount" : 128.0
}
{
"_id" : "D",
"count" : 5.0,
"totalAmount" : 422.0
}
Promedio
¿Cómo obtener el monto promedio de las transacciones de débito y crédito?
> db.transactions.aggregate(
[
{
$group : {
_id : '$cr_dr', // group by type of transaction (debit or credit)
count : {$sum : 1}, // number of transaction for each type
totalAmount : {$sum : { $sum : ['$amount', '$fee']}}, // sum
averageAmount : {$avg : { $sum : ['$amount', '$fee']}} // average
}
}
]
)
El resultado es
{
"_id" : "C", // Amounts for credit transactions
"count" : 3.0,
"totalAmount" : 128.0,
"averageAmount" : 40.0
}
{
"_id" : "D", // Amounts for debit transactions
"count" : 5.0,
"totalAmount" : 422.0,
"averageAmount" : 82.0
}
Operaciones con matrices.
Cuando desee trabajar con las entradas de datos en matrices, primero debe desenrollar la matriz. La operación de desenrollado crea un documento para cada entrada en la matriz. Cuando tenga muchos documentos con arreglos grandes verá una explosión en el número de documentos.
{ "_id" : 1, "item" : "myItem1", sizes: [ "S", "M", "L"] }
{ "_id" : 2, "item" : "myItem2", sizes: [ "XS", "M", "XL"] }
db.inventory.aggregate( [ { $unwind : "$sizes" }] )
Un aviso importante es que cuando un documento no contiene la matriz, se perderá. Desde Mongo 3.2 y hasta hay una opción de desenrollar "preserveNullAndEmptyArrays" agregada. Esta opción garantiza que el documento se conserva cuando falta la matriz.
{ "_id" : 1, "item" : "myItem1", sizes: [ "S", "M", "L"] }
{ "_id" : 2, "item" : "myItem2", sizes: [ "XS", "M", "XL"] }
{ "_id" : 3, "item" : "myItem3" }
db.inventory.aggregate( [ { $unwind : { path: "$sizes", includeArrayIndex: "arrayIndex" } }] )
Partido
¿Cómo escribir una consulta para obtener todos los departamentos donde la edad promedio de los empleados que ganan menos de $ 70000 es mayor que o igual a 35?
Para eso necesitamos escribir una consulta para igualar a los empleados que tienen un salario menor o igual a $ 70000. Luego agregue la etapa agregada para agrupar a los empleados por departamento. Luego, agregue un acumulador con un campo denominado, por ejemplo, average_age para encontrar la edad promedio por departamento usando el acumulador $ avg y debajo de $ match existente y los agregados de $ group agregan otro agregado de $ match para que solo podamos recuperar los resultados con un valor de average_age. mayor que o igual a 35.
db.employees.aggregate([
{"$match": {"salary": {"$lte": 70000}}},
{"$group": {"_id": "$dept",
"average_age": {"$avg": "$age"}
}
},
{"$match": {"average_age": {"$gte": 35}}}
])
El resultado es:
{
"_id": "IT",
"average_age": 31
}
{
"_id": "Customer Service",
"average_age": 34.5
}
{
"_id": "Finance",
"average_age": 32.5
}
Eliminar documentos que tienen un campo duplicado en una colección (dedupe)
Tenga en cuenta que la opción allowDiskUse: true es opcional pero ayudará a mitigar los problemas de falta de memoria, ya que esta agregación puede ser una operación que requiere mucha memoria si el tamaño de su colección es grande, por lo que recomiendo usarla siempre.
var duplicates = [];
db.transactions.aggregate([
{ $group: {
_id: { cr_dr: "$cr_dr"},
dups: { "$addToSet": "$_id" },
count: { "$sum": 1 }
}
},
{ $match: {
count: { "$gt": 1 }
}}
],allowDiskUse: true}
)
.result
.forEach(function(doc) {
doc.dups.shift();
doc.dups.forEach( function(dupId){
duplicates.push(dupId);
}
)
})
// printjson(duplicates);
// Remove all duplicates in one go
db.transactions.remove({_id:{$in:duplicates}})