Consultar Arrays en MongoDB

MongoDBBeginner
Practicar Ahora

Introducción

En este laboratorio, aprenderá a consultar arrays de manera efectiva en MongoDB. Los arrays son una estructura de datos fundamental en MongoDB, que le permite almacenar listas de valores dentro de un campo de documento único. Este laboratorio lo guiará a través de las técnicas esenciales para trabajar con datos de arrays, desde la coincidencia de elementos simples hasta consultas más complejas que utilizan operadores especializados. Aprenderá a encontrar documentos basándose en el contenido del array, su tamaño y la posición de los elementos, que son habilidades cruciales para cualquier desarrollador que trabaje con MongoDB.

Este es un Guided Lab, que proporciona instrucciones paso a paso para ayudarte a aprender y practicar. Sigue las instrucciones cuidadosamente para completar cada paso y obtener experiencia práctica. Los datos históricos muestran que este es un laboratorio de nivel principiante con una tasa de finalización del 100%. Ha recibido una tasa de reseñas positivas del 100% por parte de los estudiantes.

Introducción y Coincidencia Básica de Arrays

En este primer paso, se conectará al servidor MongoDB, creará una base de datos e insertará algunos datos de ejemplo. Luego, realizará consultas básicas para encontrar documentos coincidiendo con elementos dentro de un array.

Primero, abra la Shell de MongoDB (mongosh) para interactuar con su base de datos. Este comando lo conectará a la instancia de MongoDB en ejecución.

mongosh

Una vez dentro de la shell, verá un prompt test>. Cambiemos a una nueva base de datos llamada arraylab. El comando use crea la base de datos si aún no existe y cambia el contexto actual a ella.

use arraylab

Ahora, insertemos algunos documentos en una nueva colección llamada products. Cada documento representa un producto y contiene dos campos de tipo array: tags y colors. Copie y pegue el siguiente comando en su shell:

db.products.insertMany([
  {
    name: "Laptop",
    tags: ["electronics", "computer", "work"],
    colors: ["silver", "black", "blue"]
  },
  {
    name: "Smartphone",
    tags: ["electronics", "mobile", "communication"],
    colors: ["red", "blue", "green"]
  },
  {
    name: "Headphones",
    tags: ["electronics", "audio", "music"],
    colors: ["black", "white"]
  }
]);

Para encontrar un documento que contenga un elemento específico en un array, puede consultar directamente ese valor. Esta consulta encuentra todos los productos que tienen la etiqueta "mobile".

db.products.find({ tags: "mobile" });

Ejemplo de Salida:

[
  {
    _id: ObjectId("..."),
    name: 'Smartphone',
    tags: [ 'electronics', 'mobile', 'communication' ],
    colors: [ 'red', 'blue', 'green' ]
  }
]

También puede encontrar documentos donde el array coincide con una secuencia exacta de elementos. Esta consulta encuentra el producto cuyo array tags es exactamente ["electronics", "computer", "work"] en ese orden específico.

db.products.find({ tags: ["electronics", "computer", "work"] });

Ejemplo de Salida:

[
  {
    _id: ObjectId("..."),
    name: 'Laptop',
    tags: [ 'electronics', 'computer', 'work' ],
    colors: [ 'silver', 'black', 'blue' ]
  }
]

Puede permanecer en la shell mongosh para los siguientes pasos. Para salir de la shell en cualquier momento, escriba exit y presione Enter.

Uso de Operadores de Consulta de Arrays $all y $in

La coincidencia simple es útil, pero MongoDB proporciona operadores potentes para consultas de arrays más complejas. En este paso, aprenderá a usar $all para hacer coincidir varios elementos independientemente del orden y $in para hacer coincidir cualquiera de una lista de elementos.

Continuaremos usando la colección products del paso anterior.

El operador $all selecciona documentos donde el campo de array contiene todos los elementos especificados. El orden de los elementos en la consulta no importa. Busquemos productos que estén disponibles tanto en "blue" como en "silver".

db.products.find({ colors: { $all: ["blue", "silver"] } });

Ejemplo de Salida:

[
  {
    _id: ObjectId("..."),
    name: 'Laptop',
    tags: [ 'electronics', 'computer', 'work' ],
    colors: [ 'silver', 'black', 'blue' ]
  }
]

El operador $in selecciona documentos donde el campo de array contiene al menos uno de los valores especificados. Actúa como una condición "OR" para los elementos del array. Busquemos productos que tengan la etiqueta "music" o la etiqueta "work".

db.products.find({ tags: { $in: ["music", "work"] } });

Ejemplo de Salida:

[
  {
    _id: ObjectId("..."),
    name: 'Laptop',
    tags: [ 'electronics', 'computer', 'work' ],
    colors: [ 'silver', 'black', 'blue' ]
  },
  {
    _id: ObjectId("..."),
    name: 'Headphones',
    tags: [ 'electronics', 'audio', 'music' ],
    colors: [ 'black', 'white' ]
  }
]

Estos operadores brindan mucha más flexibilidad al buscar documentos basándose en el contenido de sus arrays.

Consultar por Tamaño y Posición de Array

A veces, el número de elementos en un array o la posición de un elemento específico es importante. Este paso cubre cómo consultar basándose en el tamaño del array usando el operador $size y por la posición del elemento usando notación de punto.

El operador $size coincide con documentos que tienen un array con un número específico de elementos. Busquemos productos que tengan exactamente dos colores disponibles.

db.products.find({ colors: { $size: 2 } });

Ejemplo de Salida:

[
  {
    _id: ObjectId("..."),
    name: 'Headphones',
    tags: [ 'electronics', 'audio', 'music' ],
    colors: [ 'black', 'white' ]
  }
]

Para consultar un elemento en una posición específica (índice) en un array, se utiliza la notación de punto en el formato "nombreCampo.indice". Recuerde que los índices de los arrays comienzan en cero, por lo que el primer elemento está en el índice 0. Esta consulta encuentra todos los productos donde el primer elemento en el array tags es "electronics".

db.products.find({ "tags.0": "electronics" });

Ejemplo de Salida:

[
  {
    _id: ObjectId("..."),
    name: 'Laptop',
    tags: [ 'electronics', 'computer', 'work' ],
    colors: [ 'silver', 'black', 'blue' ]
  },
  {
    _id: ObjectId("..."),
    name: 'Smartphone',
    tags: [ 'electronics', 'mobile', 'communication' ],
    colors: [ 'red', 'blue', 'green' ]
  },
  {
    _id: ObjectId("..."),
    name: 'Headphones',
    tags: [ 'electronics', 'audio', 'music' ],
    colors: [ 'black', 'white' ]
  }
]

Ahora, busquemos un producto donde el segundo color (índice 1) sea "black".

db.products.find({ "colors.1": "black" });

Ejemplo de Salida:

[
  {
    _id: ObjectId("..."),
    name: 'Laptop',
    tags: [ 'electronics', 'computer', 'work' ],
    colors: [ 'silver', 'black', 'blue' ]
  }
]

Consultar Arrays de Documentos Incrustados

Un patrón común y potente en MongoDB es tener arrays que contienen otros documentos. Estos se conocen como documentos incrustados o anidados. Consultar estos requiere un operador especial, $elemMatch, para asegurar que todas las condiciones se apliquen al mismo elemento del array.

Primero, agreguemos algunos productos nuevos que tengan un array specs. Cada elemento en el array specs es un documento con los campos ram, storage y price.

db.products.insertMany([
  {
    name: "Gaming Laptop",
    tags: ["electronics", "computer", "gaming"],
    specs: [
      { ram: 16, storage: 512, price: 1200 },
      { ram: 32, storage: 1024, price: 2000 }
    ]
  },
  {
    name: "Office Laptop",
    tags: ["electronics", "computer", "work"],
    specs: [
      { ram: 8, storage: 256, price: 600 },
      { ram: 16, storage: 512, price: 800 }
    ]
  }
]);

Ahora, supongamos que queremos encontrar un portátil que tenga una configuración con al menos 16GB de RAM y un precio inferior a $1000. Una consulta simple podría parecer correcta pero puede llevar a resultados erróneos. Por ejemplo, db.products.find({ "specs.ram": { $gte: 16 }, "specs.price": { $lt: 1000 } }) coincidiría con un documento si un documento incrustado tiene suficiente RAM y otro diferente tiene un precio lo suficientemente bajo.

Para asegurar que un único documento incrustado en el array cumpla todas las condiciones, debe usar el operador $elemMatch.

db.products.find({
  specs: {
    $elemMatch: { ram: { $gte: 16 }, price: { $lt: 1000 } }
  }
});

Esta consulta encuentra correctamente solo el "Office Laptop", porque tiene un elemento de especificación { ram: 16, storage: 512, price: 800 } que cumple ambas condiciones simultáneamente.

Ejemplo de Salida:

[
  {
    _id: ObjectId("..."),
    name: 'Office Laptop',
    tags: [ 'electronics', 'computer', 'work' ],
    specs: [
      { ram: 8, storage: 256, price: 600 },
      { ram: 16, storage: 512, price: 800 }
    ]
  }
]

Proyectar Campos de Array

A menudo, no necesita que se devuelva el documento completo de una consulta. La proyección le permite especificar qué campos incluir o excluir. Para los arrays, MongoDB proporciona operadores de proyección especiales como $slice para controlar qué elementos del array se devuelven.

El operador de proyección $slice devuelve un subconjunto de un array. Puede especificar un número positivo para obtener los primeros N elementos, o un número negativo para obtener los últimos N elementos.

Recuperemos todos los productos pero solo devolvamos el name y los dos primeros tags para cada uno. El primer argumento de find, {}, es un documento de consulta vacío que coincide con todos los documentos. El segundo argumento es el documento de proyección. Usamos _id: 0 para excluir el campo _id predeterminado.

db.products.find({}, { name: 1, tags: { $slice: 2 }, _id: 0 });

Ejemplo de Salida:

[
  { "name": "Laptop", "tags": ["electronics", "computer"] },
  { "name": "Smartphone", "tags": ["electronics", "mobile"] },
  { "name": "Headphones", "tags": ["electronics", "audio"] },
  { "name": "Gaming Laptop", "tags": ["electronics", "computer"] },
  { "name": "Office Laptop", "tags": ["electronics", "computer"] }
]

Otro operador de proyección útil es el operador posicional $. Cuando consulta un array, este operador asegura que solo se devuelva el primer elemento que coincidió con la condición de consulta en el campo del array proyectado.

Busquemos productos con la etiqueta "mobile" y devolvamos solo el name y esa etiqueta coincidente específica del array tags.

db.products.find({ tags: "mobile" }, { name: 1, "tags.$": 1, _id: 0 });

Ejemplo de Salida:

[{ "name": "Smartphone", "tags": ["mobile"] }]

Esto es muy eficiente para recuperar solo las partes relevantes de un array grande sin tener que procesar el array completo en su aplicación.

Resumen

En este laboratorio, ha aprendido las técnicas fundamentales para consultar arrays en MongoDB. Comenzó con la coincidencia de elementos básicos y progresó al uso de potentes operadores de array como $all, $in y $size. También exploró cómo consultar por la posición de un elemento y cómo consultar correctamente arrays de documentos incrustados utilizando $elemMatch. Finalmente, aprendió a dar forma a la salida de sus consultas proyectando elementos de array específicos utilizando $slice y el operador posicional $. Estas habilidades son esenciales para administrar y recuperar datos de manera efectiva de estructuras de documentos complejas en MongoDB.