Contenido del curso
Operaciones básicas
Etapas de Aggregation Framework
Operaciones avanzadas
Performance y optimización
Próximos pasos
Filtrar documentos anidados con $redact
Resumen
El operador $redact en MongoDB te permite incluir o excluir partes completas de un documento, incluidos sus subdocumentos, según una condición lógica. Es una herramienta poderosa cuando necesitas filtrar contenido anidado dentro de un pipeline de agregación, algo que $match no resuelve con la misma profundidad.
¿Qué hace el operador $redact y en qué se diferencia de match?
Mientras $match filtra documentos completos según una condición, $redact actúa a nivel de estructura interna. Evalúa cada nivel del documento y decide si lo conserva o lo descarta antes de pasar a las siguientes etapas del pipeline.
¿Qué es $redact en MongoDB? Es un operador de agregación que evalúa una condición sobre cada documento y subdocumento, y decide si lo mantiene con
$$KEEPo lo elimina con$$PRUNE.
Esto significa que si excluyes un campo en una etapa temprana, ese campo y todo lo que contiene ya no estará disponible en las etapas posteriores. Por eso conviene planear bien dónde lo colocas dentro del flujo.
¿Cómo se construye una consulta con $redact paso a paso?
El reto consiste en omitir todas las propiedades de Airbnb cuya calificación esté por debajo de 90. Para lograrlo, vas a construir una condicional explícita usando $cond, porque MongoDB no interpreta automáticamente un if suelto como estructura condicional.
¿Qué estructura debe tener la condición?
La lógica se arma con tres bloques: la condición que evalúas, qué hacer si se cumple y qué hacer si no. En este caso, la referencia es el campo review_scores.review_scores_rating, que vive dentro de un subobjeto.
javascript db.listingsAndReviews.aggregate([ { $redact: { $cond: { if: { $gte: ["$review_scores.review_scores_rating", 95] }, then: "$$KEEP", else: "$$PRUNE" } } }, { $count: "total" } ])
Aquí $$KEEP mantiene el documento cuando la calificación es igual o mayor a 95, y $$PRUNE lo elimina cuando no cumple. Son variables especiales del sistema que $redact reconoce de forma nativa.
¿Por qué es necesario envolver la condición en $cond?
Si escribes if, then y else directamente, MongoDB lanza un error. El operador $cond es el que le dice al motor que estás trabajando con una condicional, así que debe contener todo el bloque de evaluación.
¿Cuál es la diferencia entre $$KEEP y $$PRUNE?
$$KEEPconserva el documento o subdocumento actual, mientras que$$PRUNElo descarta junto con todo lo que contiene dentro.
¿Cómo verificar el resultado del pipeline con un contador?
Para medir el impacto del filtro, agregar una etapa $count al final del pipeline es la forma más directa de saber cuántos documentos sobrevivieron a la condición.
En la muestra de Airbnb usada en la clase, el resultado es claro:
- La colección original contiene aproximadamente 5600 documentos.
- Después de aplicar
$redactcon el umbral de 95, quedan 2287 documentos. - Eso representa cerca del 40% de la muestra original.
Este contador te permite validar rápidamente que la condición está bien escrita y que el campo anidado se está leyendo correctamente.
¿Cuándo conviene usar $redact y cuándo es mejor evitarlo?
Hay dos recomendaciones prácticas que vale la pena tener presentes antes de meter $redact en producción.
- Cuidado con la propagación: una vez que excluyes un campo en una etapa, ese campo desaparece para todas las etapas siguientes. Si en otra parte del pipeline necesitas ese dato, ya no lo vas a tener.
- Costo en recursos:
$redactes más costoso computacionalmente que$match. Si tu filtro se puede resolver con$match, esa es la opción más eficiente. - Casos ideales: úsalo cuando necesitas filtrar contenido anidado a varios niveles, controlar permisos por documento o aplicar reglas que
$matchno puede expresar.
La regla general es simple: si puedes resolverlo con $match, hazlo con $match. Reserva $redact para los casos donde la lógica de inclusión y exclusión vive dentro de la estructura del documento.
¿En qué otro escenario crees que $redact resolvería mejor una consulta que $match? Compártelo en los comentarios.