Mientras un array permanece embebido, cada documento representa la unidad completa. Para agrupar, ordenar o filtrar cada elemento como una fila lógica, puede ser necesario expandirlo.
N documentos
× promedio de elementos por array
≈ documentos después de $unwind
Si 100.000 órdenes tienen 20 items promedio, el siguiente stage procesa cerca de 2 millones de documentos lógicos. La cardinalidad debe estimarse antes de usarlo.
El comportamiento con valores escalares, null y missing debe probarse según versión y forma. Un schema coherente evita depender de conversiones implícitas.
Antes de unwind, puede validarse:
JavaScript
{$match:{items:{$type:'array'}}}
En auditorías, separa documentos inválidos en vez de descartarlos silenciosamente.
Usa unwind cuando stages posteriores necesitan tratar elementos como documentos. Usa map/filter cuando la unidad de salida debe seguir siendo el documento padre.
db.orders.aggregate([{$match:{
businessId,status:'confirmed',confirmedAt:{$gte: start,$lt: end }}},{$unwind:'$items'},{$group:{_id:'$items.productId',units:{$sum:'$items.quantity'},revenue:{$sum:{$multiply:['$items.quantity','$items.unitPrice']}}}},{$sort:{revenue:-1}}]);
El input de $group es el número de líneas vendidas. Si cada orden contiene muchos items, ese volumen puede ser mucho mayor que la cantidad de órdenes.
Esto puede ser correcto, pero pierde campos si no se acumulan explícitamente y puede crear arrays grandes. Una expression $map suele ser mejor cuando no necesitas cambiar cardinalidad global.
$unwind convierte elementos de array en documentos lógicos y cambia cardinalidad. Su poder está en permitir grouping y filtering por elemento; su riesgo es multiplicar trabajo y resultados. Toda pipeline con unwind debe estimar crecimiento y comprobar duplicaciones.
Comprueba lo aprendido
¿Cómo estimas la cardinalidad después de unwind?
¿Qué hace preserveNullAndEmptyArrays?
¿Cuándo usarías $filter en vez de unwind?
¿Cómo se produce un producto cartesiano accidental?
¿Por qué un lookup one-to-one puede necesitar unwind?