Ejercicio 1 parte

Vamos a crear una base de datos para una app que nos va a permitir apuntarnos a diferentes concursos de escritura.

Los concursos de escritura tienen una categoría de la que queremos saber el nombre y la descripción. Cada concurso pertenece sólo a una categoría.

Necesitamos guardar información de los concursos. Concretamente el nombre, la descripción, su categoría, la fecha límite de entrega, quién lo organiza, el premio económico si lo hay, la edición (1ª, 2ª…) y un enlace a las bases del mismo.

A estos concursos se pueden apuntar diferentes usuarios. Del usuario queremos saber el nombre, el mail, un nick o apodo y un teléfono de contacto.

Evidentemente un usuario se puede apuntar a varios concursos y un concurso puede tener apuntados a varios usuarios.

Se pide: Modelo E/R, modelo lógico, tipos de datos e implementación en MySQL incluyendo foreign keys y un índice sobre la fecha límite en la tabla concursos.

Una vez creada la base de datos crearemos 4 categorías (ej. poesía, relato, novela, microrrelato), 5 concursos (podéis apelar a vuestra imaginación o en internet hay muchísimos….) y 4 usuarios (inventados). Los concursos tendrán una categoría. Y a cada usuario lo vamos a apuntar a 2 concursos.

Resumen BD

1.- Modelo E/R ¿Cómo? Pensando y en papel o papel digital

https://trifulcas.com/introduccion-bd-relacionales/

Modelo Entidad relación

Conceptualizar datos del mundo real

Entidades: Son aquellos objetos de los que necesitamos almacenar alguna información. Ejemplo: Cliente, venta, alumno, empresa…
¿Cómo identificamos las entidades? El que pide la BD nos tiene que dar esta información. Los datos ya existen.

Relaciones entre las entidades.
1) Si hay o no hay relación
2) Tipo de relación

1)
Saber si hay o no relación tenemos que pensar si entre dos entidades hay una relación directa o por el contrario hay una relación pero a través de otra entidad.
Alumnos — Cursos — Profesores
¿Alumnos — Profesores? NO

2) 1-1, 1-n, n-n ¿Cómo lo sabemos? Preguntando.
¿De cuantos se puede matricular un alumno? N
¿De cuantos alumnos de compone un curso? N
Alumnos (N)—(N) Cursos
¿Cuantos cursos puede dar un profesor? N
¿Un curso cuantos profesores lo imparten? 1
Cursos (N) —(1) Profesores

Atributos de cada entidad: La información necesaria de cada una de las entidades. Ojo porque hay atributos que no están en la entidad sino en la relación.
Ej: Nota de alumno no está ni en el alumno ni en el curso, está en la relación.

Todo esto me devuelve un modelo de datos en papel o dibujo digital o incluso en un texto
Alumnos (N)–(N) Cursos (N)–(1) Profesores

Alumno: Nombre, dni, email, dirección
Curso: Nombre, créditos, precio
Profesor: Nombre, DNI, dirección
Alumno-Curso: Nota

2.- Pasar el modelo ER al modelo lógico
Teníamos unas reglas:https://trifulcas.com/reglas-para-la-transformacion-del-modelo-e-r-al-modelo-logico/

3.- Tipos de datos: varchar tamaño, tipos numéricos, ojo con los decimales. Cuidado con los campos que parecen números y no lo son…

https://trifulcas.com/tipos-de-datos-en-mysql/

4.- Implementar la base de datos.
a) Workbench
b) PHPMyAdmin
c) DDL (create table….)

5.- Implementar las foreignkeys para asegurar la integridad referencial. Si queremos añadir algún índice también. Recordad que toda foreign key debería tener un índice.

https://trifulcas.com/enlaces-sobre-indices/

6.- CRUD
INSERT, UPDATE y DELETE Cuidadito con esto. UPDATE y DELETE siempre con WHERE

https://trifulcas.com/sql-sentencias-creacion-de-datos-ddl/

7.- SELECT: WHERE condiciones para la selección de registros. AND OR y NOT
Operadores: <,>,=,<>, !=, LIKE, BETWEEN, IN

https://www.w3schools.com/sql/sql_like.asp

not
and
or

condicion1 and condicion2 or condicion3
1.- Evalua condicion1 and condicion2
2.- El resultado se evalua or condicion3

cond1 cond2 cond3 res
true true true true
true true false true
true false true true
true false false false
false true true true
false true false false
false false true true
false false false false

https://www.mysqltutorial.org/mysql-where/

https://es.wikipedia.org/wiki/Tabla_de_verdad

8.- JOIN Si nuestra BD es relacional, debemos relacionar las tablas. Utilizamos JOIN ¿Cómo? Miro que información me piden, busco las tablas que la contengan y creo el camino con JOIN desde una tabla a otra. OJO las claves.

9.- LEFT y RIGHT JOIN cuando necesito datos que no tienen registros relacionados. Siempre apuntando a la tabla de la que quiero todos los registros.

10.- Consultas agrupadas: GROUP BY. Nos permite utilizar funciones de agregado por los valores de un campo. COUNT, SUM, AVG, MIN, MAX. No nos olvidemos agrupar por el campo ‘id’ y no por valores como ‘nombre’ que pueden repetirse.

https://trifulcas.com/ejemplos-subconsultas/

11.- Mysql tiene funciones para manipular los datos de los campos tanto para verlos como para utilizarson en una condición. Matemáticas, de cadena, de fecha,….

https://trifulcas.com/ejemplos-funciones-mysql/

12. Subconsultas

utilizar consultas dentro de la condición de una consulta.

https://trifulcas.com/subconsultas/

Ejercicio datos geográficos

Con la colección que se adjunta al final, realizar las siguientes operaciones:

Encontrar la ciudad que tiene una población (‘pop’) mayor de 40000
Encontrar las ciudades que tienen en ‘loc’ un valor entre 37 y 42. Puede ser cualquier valor pero ese valor tiene que cumplir las dos condiciones
Encontrar las ciudades de ‘LA’ con una población menor de 10000 habitantes
Encontrar las ciudades con una población menor de 1000 habitantes pero sólo mostrar la ciudad y el estado
Modificar la ciudad ‘CUSHMAN’ y ponerle una población de 37231 habitantes.
Modificar las ciudades de ‘LA’ con menos de 1000 habitantes y ponerles en el estado ‘##’
Eliminar las ciudades con menos de 500 habitantes.

db.ciudades.insertMany([{ "_id" : "01001", "city" : "AGAWAM", "loc" : [ -72.622739, 42.070206 ], "pop" : 15338, "state" : "MA" },
{ "_id" : "01002", "city" : "CUSHMAN", "loc" : [ -72.51564999999999, 42.377017 ], "pop" : 36963, "state" : "MA" },
{ "_id" : "01005", "city" : "BARRE", "loc" : [ -72.10835400000001, 42.409698 ], "pop" : 4546, "state" : "MA" },
{ "_id" : "01007", "city" : "BELCHERTOWN", "loc" : [ -72.41095300000001, 42.275103 ], "pop" : 10579, "state" : "MA" },
{ "_id" : "01008", "city" : "BLANDFORD", "loc" : [ -72.936114, 42.182949 ], "pop" : 1240, "state" : "MA" },
{ "_id" : "01010", "city" : "BRIMFIELD", "loc" : [ -72.188455, 42.116543 ], "pop" : 3706, "state" : "MA" },
{ "_id" : "01011", "city" : "CHESTER", "loc" : [ -72.988761, 42.279421 ], "pop" : 1688, "state" : "MA" },
{ "_id" : "01012", "city" : "CHESTERFIELD", "loc" : [ -72.833309, 42.38167 ], "pop" : 177, "state" : "MA" },
{ "_id" : "01013", "city" : "CHICOPEE", "loc" : [ -72.607962, 42.162046 ], "pop" : 23396, "state" : "MA" },
{ "_id" : "29372", "city" : "PACOLET", "loc" : [ -81.758703, 34.901708 ], "pop" : 4129, "state" : "SC" },
{ "_id" : "29374", "city" : "GLENN SPRINGS", "loc" : [ -81.85785300000001, 34.774808 ], "pop" : 4588, "state" : "SC" },
{ "_id" : "29376", "city" : "ROEBUCK", "loc" : [ -81.95255, 34.8688 ], "pop" : 5009, "state" : "SC" },
{ "_id" : "29379", "city" : "UNION", "loc" : [ -81.62023499999999, 34.726855 ], "pop" : 22553, "state" : "SC" },
{ "_id" : "29384", "city" : "WATERLOO", "loc" : [ -82.087968, 34.33673 ], "pop" : 2992, "state" : "SC" },
{ "_id" : "29385", "city" : "WELLFORD", "loc" : [ -82.09270600000001, 34.951394 ], "pop" : 6637, "state" : "SC" },
{ "_id" : "29388", "city" : "WOODRUFF", "loc" : [ -82.044658, 34.757864 ], "pop" : 10206, "state" : "SC" },
{ "_id" : "29401", "city" : "CHARLESTON", "loc" : [ -79.93706899999999, 32.779506 ], "pop" : 12475, "state" : "SC" },
{ "_id" : "29403", "city" : "CHARLESTON", "loc" : [ -79.94928299999999, 32.797575 ], "pop" : 24620, "state" : "SC" },
{ "_id" : "29404", "city" : "CHARLESTON", "loc" : [ -80.06768700000001, 32.895816 ], "pop" : 5420, "state" : "SC" },
{ "_id" : "29405", "city" : "CHARLESTON", "loc" : [ -79.97644200000001, 32.851206 ], "pop" : 30621, "state" : "SC" },
{ "_id" : "30136", "city" : "DULUTH", "loc" : [ -84.15793600000001, 33.98619 ], "pop" : 30932, "state" : "GA" },
{ "_id" : "30137", "city" : "EMERSON", "loc" : [ -84.75704500000001, 34.119969 ], "pop" : 1353, "state" : "GA" },
{ "_id" : "30139", "city" : "FAIRMOUNT", "loc" : [ -84.76687800000001, 34.465241 ], "pop" : 3405, "state" : "GA" },
{ "_id" : "30140", "city" : "FELTON", "loc" : [ -85.220781, 33.887066 ], "pop" : 489, "state" : "GA" },
{ "_id" : "30141", "city" : "HIRAM", "loc" : [ -84.769875, 33.867286 ], "pop" : 6613, "state" : "GA" },
{ "_id" : "30143", "city" : "JASPER", "loc" : [ -84.475881, 34.461965 ], "pop" : 8256, "state" : "GA" },
{ "_id" : "30144", "city" : "KENNESAW", "loc" : [ -84.60466, 34.028656 ], "pop" : 37120, "state" : "GA" },
{ "_id" : "30145", "city" : "KINGSTON", "loc" : [ -84.997299, 34.250053 ], "pop" : 2534, "state" : "GA" },
{ "_id" : "35089", "city" : "KELLYTON", "loc" : [ -86.04839699999999, 32.979068 ], "pop" : 1584, "state" : "AL" },
{ "_id" : "35091", "city" : "KIMBERLY", "loc" : [ -86.80841700000001, 33.768355 ], "pop" : 1045, "state" : "AL" },
{ "_id" : "35094", "city" : "LEEDS", "loc" : [ -86.57482400000001, 33.528333 ], "pop" : 10421, "state" : "AL" },
{ "_id" : "35096", "city" : "LINCOLN", "loc" : [ -86.111152, 33.605913 ], "pop" : 5033, "state" : "AL" },
{ "_id" : "35098", "city" : "LOGAN", "loc" : [ -87.038115, 34.184079 ], "pop" : 2379, "state" : "AL" },
{ "_id" : "35111", "city" : "MC CALLA", "loc" : [ -87.102379, 33.284546 ], "pop" : 8147, "state" : "AL" },
{ "_id" : "35114", "city" : "MAYLENE", "loc" : [ -86.87274499999999, 33.231694 ], "pop" : 3727, "state" : "AL" },
{ "_id" : "47124", "city" : "GREENVILLE", "loc" : [ -86.00829899999999, 38.353533 ], "pop" : 1162, "state" : "IN" },
{ "_id" : "47125", "city" : "HARDINSBURG", "loc" : [ -86.317983, 38.462599 ], "pop" : 2496, "state" : "IN" },
{ "_id" : "47126", "city" : "HENRYVILLE", "loc" : [ -85.773403, 38.539829 ], "pop" : 2648, "state" : "IN" },
{ "_id" : "47129", "city" : "CLARKSVILLE", "loc" : [ -85.524438, 38.537273 ], "pop" : 379, "state" : "IN" },
{ "_id" : "47130", "city" : "JEFFERSONVILLE", "loc" : [ -85.735885, 38.307767 ], "pop" : 56543, "state" : "IN" },
{ "_id" : "71060", "city" : "MOORINGSPORT", "loc" : [ -93.973018, 32.66258 ], "pop" : 2838, "state" : "LA" },
{ "_id" : "71061", "city" : "OIL CITY", "loc" : [ -93.983844, 32.745107 ], "pop" : 1874, "state" : "LA" },
{ "_id" : "71063", "city" : "PELICAN", "loc" : [ -93.563361, 31.896563 ], "pop" : 998, "state" : "LA" },
{ "_id" : "71064", "city" : "PLAIN DEALING", "loc" : [ -93.690534, 32.907419 ], "pop" : 4904, "state" : "LA" },
{ "_id" : "71065", "city" : "PLEASANT HILL", "loc" : [ -93.513594, 31.808577 ], "pop" : 1338, "state" : "LA" },
{ "_id" : "71862", "city" : "WASHINGTON", "loc" : [ -93.673529, 33.754596 ], "pop" : 821, "state" : "AR" },
{ "_id" : "71864", "city" : "WILLISVILLE", "loc" : [ -93.31211999999999, 33.484731 ], "pop" : 888, "state" : "AR" },
{ "_id" : "71865", "city" : "WILTON", "loc" : [ -94.135746, 33.734794 ], "pop" : 983, "state" : "AR" },
{ "_id" : "71866", "city" : "WINTHROP", "loc" : [ -94.395174, 33.858321 ], "pop" : 950, "state" : "AR" },
{ "_id" : "71901", "city" : "LAKE CATHERINE", "loc" : [ -93.02602400000001, 34.501475 ], "pop" : 27402, "state" : "AR" },
{ "_id" : "71909", "city" : "HOT SPRINGS VILL", "loc" : [ -93.00638600000001, 34.65862 ], "pop" : 8268, "state" : "AR" }])

Ejercicios sobre teléfonos

Buscar los que tengan un ‘rating’ mayor de 10
Buscar los que tengan la propiedad color
Buscar los que sean para (‘for’) ‘ac3’
Buscar los que en la propiedad ‘n’ de ‘data’ de ‘limits’ sea ‘unlimited’

Modificar el teléfono “”AC3 Case Black” y ponerle un ‘price’ de 15
Modificar los teléfonos que tengan ‘term_year’ a 1 y ponerle un monthly_price de 80
Eliminar los teléfonos que tengan un rating menor de dos

Mini ejercicio

Con los datos del mongodb:

db.inventory.insertMany([
   { item: "journal", qty: 25, tags: ["blank", "red"], dim_cm: [ 14, 21 ] },
   { item: "notebook", qty: 50, tags: ["red", "blank"], dim_cm: [ 14, 21 ] },
   { item: "paper", qty: 100, tags: ["red", "blank", "plain"], dim_cm: [ 14, 21 ] },
   { item: "planner", qty: 75, tags: ["blank", "red"], dim_cm: [ 22.85, 30 ] },
   { item: "postcard", qty: 45, tags: ["blue"], dim_cm: [ 10, 15.25 ] }
]);

Buscar los documentos que tengan en dim_cm un valor entre 10 y 15

Ejercicio MongoDB

Vamos a crear una base de datos llamada tienda.

Y dentro de la tienda vamos a crear una colección teléfonos.

Insertaremos los siguientes datos:


[{"name" : "AC3 Phone", "brand" : "ACME", "type" : "phone", "price" : 200, "rating" : 3.8,"warranty_years" : 1, "available" : true },
{  "name" : "AC7 Phone", "brand" : "ACME", "type" : "phone", "price" : 320, "rating" : 4,"warranty_years" : 1, "available" : false },
{  "name" : "AC3 Series Charger", "type" : [ "accessory", "charger" ], "price" : 19, "rating" : 2.8,"warranty_years" : 0.25, "for" : [ "ac3", "ac7", "ac9" ] },
{  "name" : "AC3 Case Green", "type" : [ "accessory", "case" ], "color" : "green", "price" : 12, "rating" : 1,"warranty_years" : 0 },
{  "name" : "Phone Extended Warranty", "type" : "warranty", "price" : 38, "rating" : 5,"warranty_years" : 2, "for" : [ "ac3", "ac7", "ac9", "qp7", "qp8", "qp9" ] },
{  "name" : "AC3 Case Black", "type" : [ "accessory", "case" ], "color" : "black", "price" : 12.5, "rating" : 2,"warranty_years" : 0.25, "available" : false, "for" : "ac3" },
{  "name" : "AC3 Case Red", "type" : [ "accessory", "case" ], "color" : "red", "price" : 12, "rating" : 4,"warranty_years" : 0.25, "available" : true, "for" : "ac3" },
{ "name" : "Phone Service Basic Plan", "type" : "service", "monthly_price" : 40,"rating" : 3, "limits" : { "voice" : { "units" : "minutes", "n" : 400, "over_rate" : 0.05 }, "data" : { "units" : "gigabytes", "n" : 20, "over_rate" : 1 }, "sms" : { "units" : "texts sent", "n" : 100, "over_rate" : 0.001 } }, "term_years" : 2 },
{  "name" : "Phone Service Core Plan", "type" : "service", "monthly_price" : 60, "rating" : 3, "limits" : { "voice" : { "units" : "minutes", "n" : 1000, "over_rate" : 0.05 }, "data" : { "n" : "unlimited", "over_rate" : 0 }, "sms" : { "n" : "unlimited", "over_rate" : 0 } }, "term_years" : 1 },
{ "name" : "Phone Service Family Plan", "type" : "service", "monthly_price" : 90,"rating" : 4, "limits" : { "voice" : { "units" : "minutes", "n" : 1200, "over_rate" : 0.05 }, "data" : { "n" : "unlimited", "over_rate" : 0 }, "sms" : { "n" : "unlimited", "over_rate" : 0 } }, "sales_tax" : true, "term_years" : 2 }]

Después crearemos las siguientes búsquedas:

Elementos cuyo ‘type’ sea ‘service’.
Elementos cuyo ‘type’ sea ‘service’ y el precio mensual > 50
Elementos cuyo ‘type’ sea ‘service’ O el precio mensual > 50

MongoDB Consultas

https://docs.mongodb.com/manual/tutorial/query-documents/

https://docs.mongodb.com/manual/reference/operator/query/#query-selectors

Si yo en sql quiero aquellos registros cuya qty > 50

where qty>50

Si yo en MongoDB quiero lo mismo tengo que ponerlo así:

qty:{$gt:50}

campo:{operador:valor}


-- Buscar todos

db.inventory.find();

-- Buscar por igualdad. El campo debe valor lo mismo que lo que le pongo

db.inventory.find( { status: "D" } )

-- Buscar usando un operador. Ojo porque la sintaxis es un poco extraña

db.inventory.find( { qty: {$gt:50} } )

-- Operador in

db.inventory.find({status:{$in:["A","D"]}});

-- Por defecto, si tenemos varias condiciones, se entiende que se tienen que cumplir todas (AND)

db.inventory.find( { status: "A", qty: { $lt: 30 } } )

db.inventory.find({
$or: [
	{status:"D"},
	{qty:{
		$lt:50
		}
	}
]
})

db.inventory.find({$or: [{status:"D"},{qty:{$lt:50}}]})

-- esto

db.inventory.find( {
     status: "A",
     $or: [ { qty: { $lt: 30 } }, { item: /^p/ } ]
} )

-- sería equivalente a: SELECT * FROM inventory WHERE status = "A" AND ( qty < 30 OR item LIKE "p%")

db.inventory.find({qty:{$gte:40,$lte:60}})

-- En búsquedas anidadas por defecto se entiende la igualdad abosulta en valores y orden:

db.inventory.find( { size: { w: 21,h: 14,  uom: "cm" } } ) -- esto no lo encuentra

db.inventory.find({size:{h:14}}) -- Esto tampoco

db.inventory.find( { size: { h: 14, w: 21, uom: "cm" } } ) -- Esto sí

-- Para buscar por un valor concreto independientemente de optras propiedades usamos el . (punto)

db.inventory.find({"size.h":8.5})

-- Podemos usar varias condiciones tanto de propiedades anidadas como de propiedades normales

db.inventory.find( { "size.h": { $lt: 15 }, "size.uom": "in", status: "D" } )

-- Al buscar en array la igualdad es como en los anidades: mismos valores en mismo orden
-- Las dos consultas siguientes nos devuelven diferentes resultados

db.inventory.find( { tags: [ "blank","red"] } )

db.inventory.find( { tags: ["red", "blank"] } )

-- Si yo omito los corchetes y uso un valor (o un operador) se busan los elementos que contengan el valor o que cumplan la condición:

db.inventory.find({tags:"red"}) -- Busca los que tengan 'red' en el array

db.inventory.find({tags:{$in:["red","blue"]}}) -- Que tengan "red" o "blue" en alguna parte del array

db.inventory.find( { dim_cm: { $gt: 25 } } ) -- Algún elemento del array sea mayor de 25

-- Las dos condiciones se tienen que cumplir pero lo pueden cumplir elementos diferentes del array
-- Es decir, una condición la puede cumplir un elemento y la otra otro.

db.inventory.find( { dim_cm: { $gt: 15, $lt: 20 } } )

-- Las dos condiciones las tiene que cumplir juntas al menos un elemento del array

db.inventory.find( { dim_cm: { $elemMatch: { $gt: 15, $lt: 20 } } } )

-- Busco en un array en una posición concreta (índice de base 0)

db.inventory.find( { "dim_cm.1": { $gt: 25 } } )

-- Buscar los documentos cuyo array tiene una longitud determinada

db.inventory.find( { "tags": { $size: 3 } } )

-- Buscar los documentos en cuyo array haya un elemento que cumpla esa condición:

db.inventory.find( { "instock.warehouse": "C" } )

db.inventory.find( { "instock.qty": {$gte:40}} )

-- Que me muestre sólo los campos 'item' y 'status'. El id se ve siempre por defecto

db.inventory.find( { status: "A" }, { item: 1, status: 1 } )

-- Que me muestre sólo los campos 'item' y 'status'. El id lo oculto

db.inventory.find( { status: "A" }, { item: 1, status: 1, _id:0 } )

-- Que se muestren todos los campos menos 'size' e 'instock'

db.inventory.find( { status: "A" }, { size:0,instock:0 } )

-- Podemos usar $slice para obtener en la proyección subconjuntos de un array, y permite valores negativos

db.inventory.find( { status: "A" }, { item: 1, status: 1, instock: { $slice: -1 } } )

-- Busca los documentos que no tengan la propiedad o que valga nulo

db.inventory.find( { item: null } )

-- Busca los documentos que no tengan la propiedad, si la tienen y vale nulo no los encuentra

db.inventory.find( { item : { $exists: false } } )

-- Busca los documentos que SI tengan la propiedad aunque valga nulo

db.inventory.find( { item : { $exists: true } } )


MongoDB insert

https://docs.mongodb.com/manual/tutorial/insert-documents/

db.collection.insertOne() Inserts a single document into a collection.
db.collection.insertMany() db.collection.insertMany() inserts multiple documents into a collection.
db.collection.insert() db.collection.insert() inserts a single document or multiple documents into a collection.

SIEMPRE empezamos con db, NO nuestra base de datos.

Si nuestra colección no existe se crea. Así que ojo con poner el nombre bien.

Ejemplo:

db.actor.insertOne({nombre:"Ana",apellidos:"Pi"});

db.actor.insertMany([{
nombre:"Eva",
apellido:"Pou",
intereses:["drama","comedia"]
},
{
nombre:"Ana",
apellido:"Ros",
pelicula:{
	titulo:"Drama en la cumbre",
	anyo:2020
	}
},
{
nombre:"Ana",
apellido:"Ros",
pelicula:{
	titulo:"Drama en la cumbro",
	anyo:2020
	}
}
])

db.inventory.insertOne(
   { item: "canvas", qty: 100, tags: ["cotton"], size: { h: 28, w: 35.5, uom: "cm" } }
)

db.inventory.insertMany([
   { item: "journal", qty: 25, tags: ["blank", "red"], size: { h: 14, w: 21, uom: "cm" } },
   { item: "mat", qty: 85, tags: ["gray"], size: { h: 27.9, w: 35.5, uom: "cm" } },
   { item: "mousepad", qty: 25, tags: ["gel", "blue"], size: { h: 19, w: 22.85, uom: "cm" } }
])

MongoDB

https://www.mongodb.com/es

Probarlo sin instalar:

https://docs.mongodb.com/manual/tutorial/getting-started/

Instalar en windows:

https://docs.mongodb.com/manual/tutorial/install-mongodb-on-windows/

https://www.genbeta.com/desarrollo/mongodb-que-es-como-funciona-y-cuando-podemos-usarlo-o-no

Tutorial básico:

https://www.diegocalvo.es/tutorial-de-mongodb-con-ejemplos/

https://geekflare.com/es/mongodb-queries-examples/

https://www.codigofuente.org/series/mongodb/