No tienes acceso a esta clase

¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera

Manipulando campos con $set

9/21
Recursos

¿Qué es el operador set?

El operador set en MongoDB es una herramienta poderosa para dar formato y modelar el resultado de tus consultas agregadas. Similar al operador project, set te permite definir campos para el resultado final. Sin embargo, a diferencia de project, set no excluye automáticamente los campos al no especificarlos, haciendo que todos los campos existentes desde la última etapa del pipeline se mantengan a menos que se indique lo contrario. Esto puede optimizar el tiempo al crear agregaciones.

¿Cuándo usar set en lugar de project?

  • Utiliza set cuando quieras agregar, modificar o generar ciertos campos basados en otros campos.
  • Prefiere project para modificaciones radicales donde necesitas controlar completamente el documento resultante.

La elección entre ambos depende de la complejidad del documento original y de cómo deseas presentarlo al final.

¿Cómo implementar el operador set en MongoDB Compass?

Para ejemplificar el uso del operador set, vamos a trabajar desde MongoDB Compass. Comenzaremos eliminando cualquier implementación previa del operador project.

{
  $set: {
    tipoDePropiedad: "$_id",
    cantidadDePropiedades: "$cantidad",
    precioPromedio: { $round: ["$precioMedia", 2] },
    propiedadesDestacadas: [
      {
        tipo: "Más baja",
        nombre: "$masBaja.name",
        precio: "$masBaja.price"
      },
      {
        tipo: "Más alta",
        nombre: "$masAlta.name",
        precio: "$masAlta.price"
      }
    ]
  }
}

Formateo de números con decimales

MongoDB proporciona operadores como $round para ajustar resultados numéricos. Por ejemplo, si deseas que el precio promedio tenga solo dos decimales para un formato visual más limpio, puedes utilizar el siguiente enfoque:

precioPromedio: { $round: ["$precioMedia", 2] }

Creación de nuevos campos con set

Genera campos nuevos agrupando datos en objetos o arrays. En el ejemplo anterior, creamos un array propiedadesDestacadas que contiene objetos con información sobre las propiedades más baratas y más caras.

propiedadesDestacadas: [
  { tipo: "Más baja", nombre: "$masBaja.name", precio: "$masBaja.price" },
  { tipo: "Más alta", nombre: "$masAlta.name", precio: "$masAlta.price" }
]

Este enfoque ofrece una manera flexible de agregar información relevante.

Combinación de set y project

Para excluir campos no deseados en el resultado final, se puede combinar set con project, eliminando duplicaciones de información innecesaria:

{
  $project: {
    _id: 0,
    precioMedia: 0,
    cantidad: 0,
    masBaja: 0,
    masAlta: 0
  }
}

Esta técnica asegura que solo los campos configurados mediante set se incluyan en el reporte final.

Ejercicio práctico: convertir precios a otra moneda

Aprovechando los conceptos adquiridos, te sugiero un emocionante reto: intenta mostrar precios en una moneda diferente, por ejemplo, convertir de dólares a euros. Esto te permitirá practicar la transformación de datos y enriquecimiento de resultados finales.

Explora, experimenta y comparte tus hallazgos en los comentarios. Así, impulsamos el aprendizaje colaborativo y extendemos nuestros conocimientos.

Aportes 5

Preguntas 0

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad?

Solución del reto:

//media del precio, y que muestre el total por cada propiedad
[
  {
    $match: {
      "address.country_code": "US",
    },
  },
  {
    $sort: {
      property_type: 1,
      price: 1,
    },
  },

  // group by $property_type
  {
    $group: {
      _id: "$property_type",
      count:{
        $sum: 1
      },
      priceAvgMedia:{
        $avg: "$price"
      },
      cheaper: {
        $first: {
          nombre: "$name",
          precio: "$price",
          direccion: "$address",
        },
      },
      moreExpensive: {
        $last: {
          nombre: "$name",
          precio: "$price",
          direccion: "$address",
        },
      },
    },
  
  {
    $set:{
      "Tipo de propiedad": "$_id",
      "Cantidad por propiedad": "$count",
      "Precio promedio por propiedad": {$round:["$priceAvgMedia",2]},
      "propiedades destacadas":[
        {
          "tipo":"cheaper",
          "nombre":"$cheaper.nombre",
          "precioDolar":"$cheaper.precio",
          "tipoCambio": 4.00,
          "precioEuro": {$multiply: ["$cheaper.precio", 4.0]}
        },
        {
          "tipo":"moreExpensive",
          "nombre":"$moreExpensive.nombre",
          "precio":"$moreExpensive.precio",
          "tipoCambio": 4.00,
          "precioEuro": {$multiply: ["$moreExpensive.precio", 4.0]}
        }
      ]
    }
  },
  {
    $project:{
      _id:0,
      priceAvgMedia:0,
      count:0,
      cheaper:0,
      moreExpensive:0
    }
  }
  
]
Mi solución: ```js // $set sirve para crear campos nuevos en los documentos de salida. // Se utiliza para agregar nuevos campos a los documentos de entrada o para actualizar los valores de los campos existentes. use("sample_airbnb") db.listingsAndReviews.aggregate([ { $match: {"address.country_code": "US"}, }, { $sort:{ "property_type": 1, "price": 1}, }, { $group: { _id: "$property_type", contarPropiedades: { $sum: 1 }, precioPromedio: { $avg: "$price" }, "masBajo": { $first: { "nombre": "$name", "precio": "$price" } }, "masAlto":{ $last: { // ultimo elemento (mas caro) "nombre": "$name", "precio": "$price" } } } }, { $set:{ "Tipo de propiedad": "$_id", "Cantidad de propiedades": "$contarPropiedades", "Precio promedio": {$round:["$precioPromedio", 2]}, "propiedades destacadas":[ { "tipo":"Mas barata", "nombre":"$masBajo.nombre", "precioDolar":"$masBajo.precio", "precioEuro": {$round:[{$multiply: ["$masBajo.precio", 0.92]},2]} }, { "tipo":"Mas costosa", "nombre":"$masAlto.nombre", "precio":"$masAlto.precio", "precioEuro": {$round:[{$multiply: ["$masAlto.precio", 0.92]},2]} } ] } }, { // excluir campos para evitar duplicados $project: { "_id": 0, "contarPropiedades": 0, "precioPromedio": 0, "masBajo": 0, "masAlto": 0 } } ]) ```
Resolución de tarea con intervalos de precio en dólares y euros:```js use('sample_airbnb') db.listingsAndReviews.aggregate( { $match: { "address.country": "United States" } }, { $sort: { property_type: 1, price: 1, }, }, { $addFields: { exchangeRate: 0.9253 } }, { $group: { _id: "$property_type", countProperties: { $sum: 1 }, avgPriceDolar: { $avg: "$price" }, avgPriceEuro: { $avg: { $multiply: ["$price", "$exchangeRate"] } }, mostExpensive: { $last: { name: "$name", priceDolar: "$price", priceEuro: { $multiply: ["$price", "$exchangeRate"] }, address: "$address" } }, cheapest: { $first: { name: "$name", priceDolar: "$price", priceEuro: { $multiply: ["$price", "$exchangeRate"] }, address: "$address" } } } }, { $set: { "Tipo de Propiedad": "$_id", "Opciones Disponibles": "$countProperties", "Precios en dolares": { "Precio más barato": "$cheapest.priceDolar", "Precio más elevado": "$mostExpensive.priceDolar", "Precio Promedio": { $round: ["$avgPriceDolar", 2] }, }, "Precios en Euros": { "Precio más barato": { $round: ["$cheapest.priceEuro", 2] }, "Precio más elevado": { $round: ["$mostExpensive.priceEuro", 2] }, "Precio Promedio": { $round: ["$avgPriceEuro", 2] }, } } }, { $project: { "_id": 0, "exchangeRate": 0, "countProperties": 0, "avgPriceDolar": 0, "avgPriceEuro": 0, "cheapest": 0, "mostExpensive": 0 } }, { $limit: 10 } ) ```

Excelente!.

Uso de $project y $set:
$project:

  • Si la colección es compleja y requiere formatear datos para el resultado final.

$set:

  • Si la colección es sencillo o tiene pocos campos.
use('sample_airbnb')

db.listingsAndReviews.aggregate([
  {
    $match: {
      "address.country_code": "US"
    }
  },
  {
    $sort: {
    	property_type: 1,
      price : 1
    }
  },
  {
    $group: {
      _id: "$property_type",
      count:{
        $sum: 1
      },
      precioMedia: {
        $avg: "$price"
      },
      masBajo: {
        $first: {
          nombre: "$name",
       	 	precio: "$price",
        	direccion: "$address"
        }
      },
      masAlto: {
        $last: {
          nombre: "$name",
       	 	precio: "$price",
        	direccion: "$address"
        }
      },
    }
  },
  {
    $set:{
      "Tipo de Propiedad": "$_id",
      "Total": "$count",
      "Promedio": { $round: ["$precioMedia", 0] },
      "Precio mas Bajo": { $round: ["$masBajo.precio", 0] },
      "Precio mas Alto": { $round: ["$masAlto.precio", 0] },
      " Propiedades destacadas": [
        {
          "Tipo": "Mas bajo",
          "Nombre": "$masBajo.nombre",
          "Precio": "$masBajo.precio"
        },
        {
          "Tipo": "Mas Alto",
          "Nombre": "$masAlto.nombre",
          "Precio": "$masAlto.precio"
        }
      ]
    }
  },
  {
  $project: {
    _id: 0,
    precioMedia: 0,
    count: 0,
    masBajo: 0,
    masAlto: 0
  }
  }
])