Explica cómo populate resuelve referencias en Mongoose, qué consultas adicionales genera y cuándo conviene reemplazarlo por agregaciones o lecturas específicas.
reemplaza referencias almacenadas —normalmente ObjectId— por documentos obtenidos desde otra colección. Es una comodidad de Mongoose, no un join gratuito ni una operación ejecutada dentro del documento original.
match filtra el documento poblado; normalmente no elimina el documento padre. El resultado poblado puede quedar null o vacío. No confundas esto con filtrar órdenes que tengan un producto activo.
Para filtrar por datos relacionados puede ser más apropiado $lookup, denormalización o consultar primero la entidad relacionada.
Un límite global puede distribuirse de forma distinta a “diez por documento”. perDocumentLimit ofrece semántica por padre, pero puede generar más consultas. Comprueba versión y número real de round trips.
Cada nivel aumenta coste, payload y dificultad de autorización. Tres niveles de population suelen indicar que la API está reconstruyendo un grafo completo para una pantalla.
Population funciona con lean bajo opciones compatibles. Los resultados poblados también son objetos simples, sin métodos, getters ni virtuals normales.
Prueba transforms y TypeScript: el tipo de un path cambia de ObjectId a documento poblado, lo que puede volver ambiguo el modelo.
Population no ofrece snapshot consistente entre consultas por defecto. El documento relacionado puede cambiar entre leer padres y referencias. Si necesitas una vista histórica, usa snapshot; si necesitas consistencia transaccional, diseña la lectura y concerns explícitamente.
Population simplifica resolver referencias, pero añade consultas, payload y estados nulos. Úsalo de manera explícita, con selección, límites, índices y autorización. Cuando la relación se lee siempre junta, necesita historia o crece sin límite, reconsidera el modelo antes de añadir más populate().