16 - Documentos embebidos: definición de campos de tipo documento

Hasta ahora hemos trabajado definiendo documentos con una serie de campos que almacenan tipo de datos simples como enteros, reales, cadenas de caracteres y datos compuestos de tipo arreglo.

Según el tipo de consultas que haremos a nuestros documentos debemos definir el esquema de campos de los mismos. Supongamos que tenemos que almacenar el dato de clientes y luego hacer consultas de donde viven y discriminar por calle y número, luego puede tener sentido tener un campo dirección que sea un documento donde se almacenen por separado la calle, el número y el código postal.

Veamos con un ejemplo como creamos una colección de documentos utilizando documentos embebidos.

use base1
db.clientes.drop()

db.clientes.insertOne(
  {
    _id: 1,  
    nombre: 'Martinez Victor',
    mail: 'mvictor@gmail.com',
    direccion: {
      calle: 'Colon',
      numero: 620,
      codigopostal: 5000
    }
  }
)
db.clientes.insertOne(
  {
    _id: 2,  
    nombre: 'Alonso Carlos',
    mail: 'acarlos@gmail.com',
    direccion: {
      calle: 'Colon',
      numero: 150,
      codigopostal: 5000
    }
  }
)
db.clientes.insertOne(
  {
    _id: 3,  
    nombre: 'Gonzalez Marta',
    mail: 'gmarta@outlook.com',
    direccion: {
      calle: 'Colon',
      numero: 1200,
      codigopostal: 5000
    }
  }
)
db.clientes.insertOne(
  {
    _id: 4,  
    nombre: 'Ferrero Ariel',
    mail: 'fariel@yahoo.com',
    direccion: {
      calle: 'Dean Funes',
      numero: 23,
      codigopostal: 5002
    }
  }
)
db.clientes.insertOne(
  {
    _id: 5,  
    nombre: 'Fernandez Diego',
    mail: 'fdiego@gmail.com',
    direccion: {
      calle: 'Dean Funes',
      numero: 561,
      codigopostal: 5002
    }
  }
)

db.clientes.find()

Para recuperar todos los clientes que viven en la calle 'Colon' tenemos que plantear la siguiente consulta:

db.clientes.find({'direccion.calle':'Colon'}).pretty()

Es obligatorio disponer las comillas cuando hacemos referencia a un subcampo de un documento: 'direccion.calle'.

El resultado de ejecutar la consulta es:

MongoDB documentos embebidos

Para recuperar todos los clientes que viven en la calle 'Colon' y su número está comprendido entre 1 y 1000 tenemos que plantear la siguiente consulta:

db.clientes.find({ 'direccion.calle':'Colon','direccion.numero':{$gte:0},'direccion.numero':{$lte:1000} }).pretty()

Si ejecutamos la consulta podemos comprobar que hay dos documentos que cumplen la condición impuesta al método 'find':

MongoDB documentos embebidos

Problemas propuestos

  1. Crear la colección 'libros' en la base de datos 'base1' (eliminar la colección previamente), cargar luego 4 documentos:

    use base1
    db.libros.drop()
    
    db.libros.insertOne(
      {
        _id: 1,  
        titulo: 'El aleph',
        autor: {
          nombre: 'Borges',
          nacionalidad: 'Argentina'
        },
        editorial: ['Siglo XXI','Planeta'],
        precio: 20,
        cantidad: 50 
      }
    )
    db.libros.insertOne(
      {
        _id: 2,  
        titulo: 'Martin Fierro',
        autor: {
          nombre: 'Jose Hernandez',
          nacionalidad: 'Argentina'
        },
        editorial: ['Siglo XXI'],
        precio: 50,
        cantidad: 12
      }
    )
    db.libros.insertOne(
      {
        _id: 3,  
        titulo: 'Aprenda PHP',
        autor: {
          nombre: 'Mario Molina',
          nacionalidad: 'Española'
        },
        editorial: ['Siglo XXI','Planeta'],
        precio: 50,
        cantidad: 20
      }
    )
    db.libros.insertOne(
      {
        _id: 4,  
        autor: {
          nombre: 'Java en 10 minutos',
          nacionalidad: 'Española'
        },
        editorial: ['Siglo XXI'],
        precio: 45,
        cantidad: 1 
      }
    )
    
  2. Imprimir todos los documentos de la colección 'libros'.

  3. Imprimir todos los libros de autores de nacionalidad 'Argentina'.

  4. Imprimir los libros de 'Borges'.

  5. Imprimir todos los libros de nacionalidad 'Española' que cuestan 50 o más.

Solución
use base1
db.libros.drop()

db.libros.insertOne(
  {
    _id: 1,  
    titulo: 'El aleph',
    autor: {
      nombre: 'Borges',
      nacionalidad: 'Argentina'
    },
    editorial: ['Siglo XXI','Planeta'],
    precio: 20,
    cantidad: 50 
  }
)
db.libros.insertOne(
  {
    _id: 2,  
    titulo: 'Martin Fierro',
    autor: {
      nombre: 'Jose Hernandez',
      nacionalidad: 'Argentina'
    },
    editorial: ['Siglo XXI'],
    precio: 50,
    cantidad: 12
  }
)
db.libros.insertOne(
  {
    _id: 3,  
    titulo: 'Aprenda PHP',
    autor: {
      nombre: 'Mario Molina',
      nacionalidad: 'Española'
    },
    editorial: ['Siglo XXI','Planeta'],
    precio: 50,
    cantidad: 20
  }
)
db.libros.insertOne(
  {
    _id: 4,  
    autor: {
      nombre: 'Java en 10 minutos',
      nacionalidad: 'Española'
    },
    editorial: ['Siglo XXI'],
    precio: 45,
    cantidad: 1 
  }
)

db.libros.find().pretty()

db.libros.find({'autor.nacionalidad':'Argentina'}).pretty()

db.libros.find({'autor.nombre':'Borges'}).pretty()

db.libros.find({'autor.nacionalidad':'Argentina',precio:{$gte:50}}).pretty()