1. Introducción

En el siguiente post instalaremos MongoDB en Docker. Crearemos una base de datos, una colección, insertaremos datos de prueba y haremos uso de las funciones find y aggregation para extraer información.

2. Instalación en Docker

La instalación de MongoDB la haremos sobre Docker haciendo uso de docker-compose. Si no tienes Docker instalado, podrás ver cómo harcerlo en el post SpringBoot – Docker.

El nombre de nuestro contenedor será my-mongodb

mongo:  
  container_name: my-mongodb
  image: mongo
  ports:
    - "27017:27017"

Arrancamos nuestro contenedor docker a través de docker-compose

docker-compose up

3. Creación BD, colección e inserción de datos

Arrancamos el cliente mongo que se encuentra dentro de nuestra imagen docker

docker exec -it my-mongodb mongo

Usando el comando use seleccionamos la base de datos con la que vamos a trabajar. Si no existe se crea.

use development

Creamos la colección user

db.createCollection('user')

Insertamos los siguientes documentos en nuestra colección user.

db.user.insert({"_id":"1","name":"admin","surname":"admin","gender":"male","roles":["ROLE_ADMIN"]})
db.user.insert({"_id":"2","name":"Jorge","surname":"HernándezRamírez","gender":"male","roles":["ROLE_ADMIN"],"teams":[{"name":"UD.LasPalmas","sport":"Football"},{"name":"RealMadrid","sport":"Football"},{"name":"McLaren","sport":"F1"}]})
db.user.insert({"_id":"3","name":"Jose","gender":"male","surname":"HernándezRamírez","roles":["ROLE_USER"],"teams":[{"name":"UD.LasPalmas","sport":"Football"},{"name":"MagnusCarlsen","sport":"Chess"}]})
db.user.insert({"_id":"4","name":"Raul","surname":"GonzálezBlanco","gender":"male","roles":["ROLE_USER"],"teams":[{"name":"RealMadrid","sport":"Football"},{"name":"RealMadrid","sport":"Basketball"}]})
db.user.insert({"_id":"5","name":"Constanza","surname":"RamírezRodríguez","gender":"female","roles":["ROLE_USER"],"teams":[{"name":"UD.LasPalmas","sport":"Football"}]})

4. Find

1. Obtener todos los documentos

db.user.find();

Resultado

{ "_id" : "1", "name" : "admin", "surname" : "admin", "gender" : "male", "roles" : [ "ROLE_ADMIN" ] }
{ "_id" : "2", "name" : "Jorge", "surname" : "Hernández Ramírez", "gender" : "male", "roles" : [ "ROLE_ADMIN" ], "teams" : [ { "name" : "UD. Las Palmas", "sport" : "Football" }, { "name" : "Real Madrid", "sport" : "Football" }, { "name" : "McLaren", "sport" : "F1" } ] }
{ "_id" : "3", "name" : "Jose", "gender" : "male", "surname" : "Hernández Ramírez", "roles" : [ "ROLE_USER" ], "teams" : [ { "name" : "UD. Las Palmas", "sport" : "Football" }, { "name" : "Magnus Carlsen", "sport" : "Chess" } ] }
{ "_id" : "4", "name" : "Raul", "surname" : "González Blanco", "gender" : "male", "roles" : [ "ROLE_USER" ], "teams" : [ { "name" : "Real Madrid", "sport" : "Football" }, { "name" : "Real Madrid", "sport" : "Basketball" } ] }
{ "_id" : "5", "name" : "Constanza", "surname" : "Ramírez Rodríguez", "gender" : "female", "roles" : [ "ROLE_USER" ], "teams" : [ { "name" : "UD. Las Palmas", "sport" : "Football" } ] }

2. Obtener los documentos cuyo atributo gender tenga al valor male. No mostrar los atributos _id, surname, gender, roles y teams

db.user.find({gender: 'male'}, {_id: 0, surname: 0, gender:0, roles:0, teams:0});

Resultado

{ "name" : "admin" }
{ "name" : "Jorge" }
{ "name" : "Jose" }
{ "name" : "Raul" }

3. Mostrar documentos que contengan como equipo a la UD. Las Palmas.

 db.user.find({'teams.name': 'UD. Las Palmas'});

o bien utilizando $in

db.user.find({'teams.name': {$in: ['UD. Las Palmas']}});

Resultado

{ "_id" : "2", "name" : "Jorge", "surname" : "Hernández Ramírez", "gender" : "male", "roles" : [ "ROLE_ADMIN" ], "teams" : [ { "name" : "UD. Las Palmas", "sport" : "Football" }, { "name" : "Real Madrid", "sport" : "Football" }, { "name" : "McLaren", "sport" : "F1" } ] }
{ "_id" : "3", "name" : "Jose", "gender" : "male", "surname" : "Hernández Ramírez", "roles" : [ "ROLE_USER" ], "teams" : [ { "name" : "UD. Las Palmas", "sport" : "Football" }, { "name" : "Magnus Carlsen", "sport" : "Chess" } ] }
{ "_id" : "5", "name" : "Constanza", "surname" : "Ramírez Rodríguez", "gender" : "female", "roles" : [ "ROLE_USER" ], "teams" : [ { "name" : "UD. Las Palmas", "sport" : "Football" } ] }

4. Mostrar aquellos usuarios que sigan a la UD. Las Palmas y a Magnus Carlsen.

 db.user.find({'teams.name': {$all: ['UD. Las Palmas', 'Magnus Carlsen']}});

o bien

db.user.find({'teams.name': {$in: ['UD. Las Palmas']}, 'teams.name': {$in: ['Magnus Carlsen']}});

Resultado

{ "_id" : "3", "name" : "Jose", "gender" : "male", "surname" : "Hernández Ramírez", "roles" : [ "ROLE_USER" ], "teams" : [ { "name" : "UD. Las Palmas", "sport" : "Football" }, { "name" : "Magnus Carlsen", "sport" : "Chess" } ] }

5. Contar los documentos que tengan el rol ‘ROLE_ADMIN’

 db.user.find({roles: 'ROLE_ADMIN'}).count()

Resultado

2

4. Aggregate

Las agregaciones las utilizamos para realizar operaciones de agrupación de datos, conteo, sumas etc. Es el análogo al group by en las bases de datos relacionales.

1. Obtener el número de hombres y mujeres del sistema.

db.user.aggregate(
   {$group: {_id: "$gender", count : {$sum : 1}}}
)

Resultado

{ "_id" : "female", "count" : 1 }
{ "_id" : "male", "count" : 4 }

2. Obtener el número de usuarios en los que el Real Madrid es su equipo.

db.user.aggregate(
   {$match: {"teams.name": "Real Madrid"}},
   {$group: {_id: null, count: {$sum: 1}}
})

Resultado

{ "_id" : null, "count" : 2 }

3. Unwind.
$unwind es el análogo a hacer un join en sql. Deconstruye el array permitiendo obtener tantos documentos diferentes como elementos existen.

db.user.aggregate(
   {$unwind: "$teams"},
   {$match: {"teams.name": "Real Madrid"}})

Resultado

{ "_id" : "2", "name" : "Jorge", "surname" : "Hernández Ramírez", "gender" : "male", "roles" : [ "ROLE_ADMIN" ], "teams" : { "name" : "Real Madrid", "sport" : "Football" } }
{ "_id" : "4", "name" : "Raul", "surname" : "González Blanco", "gender" : "male", "roles" : [ "ROLE_USER" ], "teams" : { "name" : "Real Madrid", "sport" : "Football" } }
{ "_id" : "4", "name" : "Raul", "surname" : "González Blanco", "gender" : "male", "roles" : [ "ROLE_USER" ], "teams" : { "name" : "Real Madrid", "sport" : "Basketball" } }

4. Obtener el número de veces que el Real Madrid es un equipo de un usuario.

 db.user.aggregate(
   {$unwind: "$teams"},
   {$match: {"teams.name": "Real Madrid"}},
   {$group: {_id: null, count: {$sum: 1}}}
)

Resultado

{ "_id" : null, "count" : 3 }

5. $last, $addToSet

  • $last nos permite obtener el último elementos encontrado al hacer el groupby.
  • $addToSet nos permite obtener una lista de un atributo de los documentos que intervienen en el groupby.
db.user.aggregate(
   {$group: {_id: "$gender", count : {$sum : 1}, lastName: {$last: "$name"}, nameList: {$addToSet: "$name"}}},
   {$project: {_id: 0}})

Resultado

{ "count" : 1, "lastName" : "Constanza", "nameList" : [ "Constanza" ] }
{ "count" : 4, "lastName" : "Raul", "nameList" : [ "Raul", "Jose", "Jorge", "admin" ] }