Ejercicios con MongoDB (en Cloud y mongosh)

Ejercicios para aprender a usar MongoDB usando Atlas (Cloud DB). Necesitas estudiar el tema Bases de Datos NoSQL.

Preparando tu entorno de desarrollo

Para hacer los ejercicios lo primero es tener una instancia de mongoDB operativa y usar la consola.

Crea tu servidor (Cloud Server):

Necesitas tener una cuenta en el servicio Atlas de MongoDB para poder usarlo como servicio cloud.

  1. Te registras, creas tu cuenta y tu cluster (SGBD). Versión Gratuita

  2. Crearás tu usuario y sistema de autenticación

  3. Una vez que te das de alta, puedes cargar los datasets disponibles (vía web al configurar el cluster).

Configura el acceso local

Los ejercicios son para realizar usando mongosh (cambiarían si usas otro método de conexión)

  1. Instala mongosh

  2. Configura la conexión (cadena de conexión)

  3. Conéctate y prueba (show databases)

Usa la consola

Una vez que tengas acceso local a tu servidor local, la idea es que uses, con cierta soltura, la consola mongosh. Resuelve las siguientes tareas:

  1. ¿Cómo ves la ayuda de la consola?

  2. ¿Qué versión estás usando?

  3. ¿Qué BD tienes disponibles?

  4. ¿Como te conectas a una BD concreta? Por ejemplo sample_sales

  5. ¿Cómo sabes las colecciones que hay en una BD concreta? Por ejemplo sample_mflix

  6. ¿Cómo borras la pantalla?

  7. ¿Cómo sales de la consola?

Para los ejercicios usaremos la BD sample_restaurants

Ejercicios de Consultas

Trabajamos sobre la colección restaurants. Se trata de mostrar los documentos (recuerda que la búsqueda devuelve una colección de documentos):

  1. Todos los documentos de la colección restaurants

  2. El primer documento de la colección

  3. Los que sean de cocina griega (Greek)

  4. Los que sean de cocina griega y tengan una nota (grade) de B

  5. Los que estén en una determinada ciudad

  6. Los que tengan restaurante id 40370781, 40369158 y 40367677

  7. Los que hayan tenido una valoración (score) de al menos 30 puntos

  8. Los que sean de cocina Italian o Mexican

  9. Los que sean de cocina Italina o Mexican y estén en Manhattan (borough)

  10. Los peores (con algún score menor de 5) de los de comida italiana

Solución
use sample_restaurants
db.restaurants.find();
db.restaurants.findOne();
db.restaurants.find({cuisine: 'Greek'});
db.restaurants.find({cuisine: 'Greek', "grades.grade": 'B'});
db.restaurants.find({ "address.street": "Utica Ave" })
db.restaurants.find({restaurant_id: {$in: ['40370781','40369158','40367677']}});
db.restaurants.find({score: {$gt 30}});
db.restaurants.find({ $or: [ { cuisine: "Italian" }, { cuisine: "Mexican" } ] })
db.restaurants.find({ borough: 'Manhattan', $or: [ { cuisine: "Italian" }, { cuisine: "Mexican" } ]})
db.restaurants.find({ $or: [ {cuisine: "Italian"} , {"grades.score": {$lt: 5}} ]})

Ejercicios de Proyección

Los ejercicios de proyección buscan mostrar sólo algunos campos de los documentos que resultan de la consulta. Seguimos trabajando con la colección restaurants

  1. ¿Cuales son los nombres de los restaurantes que tenemos almacenados?

  2. ¿Y qué tipos de cocina?

  3. ¿Y el nombre de restaurante, el tipo de cocina y barrio (borough) en el que está?

  4. ¿Cuales son los nombres de los restaurantes que ofrecen comida italiana?

  5. ¿Cual es el nombre, la calle y el barrio de los peores (con algún score menor de 5) de los de comida italiana?

Solución
db.restaurants.find({}, {name: 1});
// Añado _id:0 para que no aparezca (sólo funciona para este campo especial)
// Ojo que realmente muestra el campo cuisine (recuerda el concepto de DISTINCT en SQL, aquí se haría de otra forma)
db.restaurants.find({}, {cuisine: 1,_id: 0});
db.restaurants.find({}, {name: 1, cuisine: 1, borough: 1, _id: 0});
db.restaurants.find({cuisine: 'Italian'}, {name: 1, _id: 0});
db.restaurants.find({ $or: [ {cuisine: "Italian"} , {"grades.score": {$lt: 5}} ]}, {name: 1, "address.street": 1, "borough": 1, _id: 0})

Ejercicios de Actualización

Vamos a trabajar ahora con la colección movies de la BD sample_mflix

  1. Actualiza el campo year de la pelicula de título “Civilization” a “1985”

  2. Incrementar en 1 el número de comentarios (num_mflix_comments) de todas las películas del tipo (type) “movie”

  3. Añadir un nuevo campo «pub_es» y con el valor “verdadero”

  4. Renombra el nombre del campo num_mflix_comments a comentarios (en todas las películas)

  5. Actualiza el campo comentarios multiplicándolo por un factor de 4 en las película “Civilization”

  6. Actualiza el campo comentarios de todas las películas, sumándole 10

  7. Actualiza el campo year de la película “Civilization”, estableciéndolo en el momento actual (timestamp)

  8. Actualiza el campo cast de la película “Civilization” añadiendole el actor “Perico de los Palotes”

  9. Actualiza el campo year de las peliculas con duración (runtime) mayor a 100 para que sea 100 (es decir, no habrá ninguna duración mayor que 100)

  10. Actualiza todas las películas cuya duración (runtime) sea de 100, para que no tengan el género (genres) “Action”. Es decir, quitarle el género Action del array.

Solución
use sample_mflix
show collections

db.movies.updateOne({title: "Civilization"},{$set: {year: 1985}});
db.movies.updateMany({type: "movie"},{$inc: {num_mflix_comments: 1}});
db.movies.updateMany({},{$set: {pub_es: true}});
db.movies.updateMany({},{$rename: {num_mflix_comments: "comentarios"}});
db.movies.updateOne({title: 'Civilization'},{$mul: {comentarios: 4}});
db.movies.updateMany({},{$inc: {comentarios: 10}});
db.movies.updateOne({title: 'Civilization'},{$currentDate: {year: true }});
db.movies.updateOne({title: 'Civilization'},{$push: {cast: "Perico de los Palotes" }});
db.movies.updateMany({runtime: {$gt: 100}}, {$set: {duration: 100}});
db.movies.updateMany({runtime: 100}, {$pull: {genres: 'Action'}});

Ejercicios de Borrado

Usando la colección movies,

  1. Borra una específica, usando su _id (busca uno cualquiera)

  2. Borra las que sean del año 1985

  3. Borra las que sean el género Action

  4. Borra las que tengan una puntuación (rating) en imdb menor a 3.4

  5. Borra las que sean se hayan lanzado (released) antes del 15 de Julio del 2001 (ISODate(«2001-07-15»))

  6. Borra la que se titula Meshes of the Afternoon

  7. Borra sólo una que tenga el campo pub_es en verdadero (true)

  8. Borra las que haya dirigido Steven Spielberg

  9. Borra las películas de entre los años 1950 y 1970 y que tengan menos de 80 votos en imdb

  10. Borrar todos los documentos de la colección

Solución
// Cogí uno de ejemplo, puedes hacer la prueba con otro _id

db.movies.deleteOne({ _id: ObjectId("603ed51abeb1242b14d72537") });
db.movies.deleteMany({ year: 1985});
db.movies.deleteMany({ genres: "Action" });
db.movies.deleteMany({"imdb.rating": {$lt: 3.4}});
db.movies.deleteMany({ released: { $lt: ISODate("2001-07-15") } });
db.movies.deleteOne({title: 'Meshes of the Afternoon'});
db.movies.deleteOne({pub_es: {$exists: 1}});
db.movies.deleteMany({ directors: "Steven Spielberg" });
db.movies.deleteMany({"imdb.votes": {$lt: 80}, year: {$gt: 1950}, year: {$lt: 1970}});
db.movies.deleteMany({});

Ejercicios de Agregación

Usando la colección movies,

  1. Obtener la cantidad total de películas en la colección

  2. Obtener 3 películas de la colección

  3. Obtener los titulos de 5 películas de la colección

  4. Calcular el promedio de duración de todas las películas

  5. Contar cuántas películas hay por tipo (type)

  6. Dime el título de las 5 películas con mayor duración

  7. Calcular la puntuación promedio de imdb, por tipo de pelicula

  8. Dime el número de comentarios de películas, según el año (year)

  9. Encontrar las películas del año 1980, y mostrar el título y número de votos en imdb, ordenadas por el número de votos, de mayor a menor número

  10. Cuantas películas a partir del año 2001, son del tipo «series»

Solución
// Siempre se agrupa por un _id (porque el resultado tiene que ser un documento con un _id)
db.movies.aggregate([           { $group:           { _id: null, total: { $sum: 1 } }           }       ]);
db.movies.aggregate([ {$limit: 3}]);
db.movies.aggregate([ {$limit: 5}, {$project: {title: 1, _id: 0}}]);
db.movies.aggregate([ { $group: { _id: null, media: { $avg: "$runtime" } } }            ]);
db.movies.aggregate([ { $group: { _id: "$type", Total: { $sum: 1 } } }] );
db.movies.aggregate([ { $sort: { "runtime": -1 } }, {$project: {title: 1}}, { $limit: 5 }] );
db.movies.aggregate([ { $group: { _id: "$type", Media: { $avg: "$imdb.rating" } } }] );
db.movies.aggregate ([{$group: {_id: "$year", total: {$sum: "$comentarios"}}}]);
db.movies.aggregate ([ {$match: {year: 1980}}, {$project: {title: 1, year: 1, _id: 0, "imdb.votes": 1}}, { $sort: {"imdb.votes": -1} }]);
db.movies.aggregate([ {$match: {year: {$gt: 2001}, type: "series"}}, {$count: "Total"}]);