En este codelab, aprenderás a configurar todo lo necesario para crear una API utilizando Node.js, Express.js y MongoDB. Crearemos endpoints para que puedas hacer tu primer CRUD.

node-express-mongo

Para poder desarrollar un servidor de node, necesitamos instalarlo, esto lo podemos hacer desde el siguiente enlace node.js.

download-node

Una vez instalado, creamos una nueva carpeta para nuestro proyecto y la abrimos con VS code. Aquí debemos abrir una nueva terminal, esto podemos hacerlo en el menú, terminal - new terminal o presionando en el teclado Ctrl+Shift+ñ, como podemos verlo en la siguiente imagen:

download-node

Iniciar un nuevo proyecto de Node.js

Para iniciar un nuevo proyecto de node debemos ejecutar el siguientes comando de npm en el terminal que acabamos de abrir

npm es el manejador de paquetes que viene por defecto cuando instalamos node, así que al realizar la instalación de node podemos utilizarlo sin problemas.

Si creamos un nuevo proyecto con los valores por defecto (omitiendo el asistente) con el comando npm init -y, se generará un archivo llamado package.json en la carpeta raíz del proyecto, donde coloca toda la información que se conoce sobre el proyecto:

{
  "name": "nombre del proyecto",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}

Esta información se irá modificando a medida que avancemos en el proyecto. Con esto ya tenemos instalado Node.js e iniciado una nueva aplicación.

Para desarrollar nuestra API vamos a necesitar una base de datos, asi que antes de comenzar con nuestro código, configuraremos MongoDB Atlas. MongoDB Atlas es un servicio de pago, pero entre sus planes nos ofrece un plan compartido que es totalmente gratuito y que nos ofrece todo lo necesario para que podamos comenzar a usar una base de datos de MongoDB de inmediato.

Registro en MongoDB Atlas

Para realizar el registro podemos ir al siguiente enlace mongoDB Atlas.

Creación de un Cluster gratuito

Una vez registrados vamos a necesitar una URI para realizar la conexión desde nuestro código con MongoDB Atlas, cuanto te registras MongoDB Atlas crea un proyecto por defecto, en este proyecto creamos un nuevo cluster, un cluster es un conjunto de servidores que trabajan juntos para almacenar y administrar los datos de tu base de datos MongoDB, aquí vamos a seleccionar la versión gratuita y el proveedor, que en este caso sugiero AWS.

mongoAtlas-registro

Obtener la URI de conexión

Una vez finalizado el registro tendremos un cluster inicial llamado Cluster0 que podremos usar de forma gratuita. Ahora vamos a necesitar una URI para realizar la conexión desde nuestra API de node. Para esto vamos a la opción que dice Connect en nuestro cluster

connect-cluster

Aquí nos pedirá crear un usuario y una contraseña para la conexión. Recuerda usar una contraseña segura.

cluster-user

Luego tendremos varias opciones de conexión, pero ya que utilizaremos Mongoose, vamos a conectarnos a través de la opción que dice Drivers.

cluster-driver

En el último paso, seleccionamos la versión del driver, que en nuestro caso será Node.js, y tendremos disponible la URL de conexión para usarla en nuestro código.

cluster-url

Ahora volvamos a VS Code y vamos a instalar los paquetes necesarios para comenzar con el desarrollo de nuestra API. Necesitaremos instalar Express para crear nuestras rutas, Mongoose realizar la conexión con la base de datos alojada en MongoDB Atlas, dotenv para manejar las variables de entorno y cors para configurar los origenes cruzados, además instalaremos un paquete que solo usaremos en desarrollo, este paquete es nodemon para que todos los cambios realizados se apliquen sin necesidad de reiniciar el servidor de node.

Para la instalación ejecutaremos los siguientes comandos en la terminal:

Una vez instalados estos paquetes, se generará una carpeta nueva llamada node_modules, la cual almacena todas las dependencias de tu proyecto y un nuevo archivo llamado package-lock.json, el cual se genera automáticamente cuando se instalan paquetes o dependencias en el proyecto. Su finalidad es mantener un historial de los paquetes instalados y optimizar la forma en que se generan las dependencias del proyecto y los contenidos de la carpeta node_modules/.

vscode-i

Además de esto, tambien hay un cambio en el archivo package.json, se agregaron 2 nuevos bloques las dependencies que muestras los paquetes de producción que instalamos y las devDependencies que muestra los paquetes que se usarán solo en desarrollo:

  "dependencies": {
    "cors": "^2.8.5",
    "dotenv": "^16.4.5",
    "express": "^4.19.2",
    "mongoose": "^8.3.5"
  },
  "devDependencies": {
    "nodemon": "^3.1.0"
  }

Comenzamos a crear nuestra API

Ya tenemos todo listo para comenzar con nuestro código, así que vamos a crear nuestro archivo main, que en este caso será index.js, si quieres cambiar este nombre por app.js por ejemplo, deberías también cambiarlo en el package.json en el bloque de main. Una vez creado el index.js en la carpeta raíz, lo abrimos y vamos a importar todas las dependencias necesarias.

  const express = require("express");
  const cors = require("cors");
  const mongoose = require("mongoose");
  require("dotenv").config();

El siguiente paso será guardar una instancia de express, configurar los cors, usar un middleware que lee los datos Json y los convierte en un objeto de JavaScript para usarlo mucho más fácil, todo esto mediante los métodos que nos brinda express.

  const app = express();
  app.use(cors());
  app.use(express.json())

Ya tenemos listo para comenzar a hacer la conexión a nuestra base de datos en mongoDB Atlas

En esta parte ya podemos hacer la conexión con la base de datos que creamos en MongoDB Atlas. Primero que todo, vamos a necesitar crear una variable de entorno para tener disponible la URL de enlace que obtuvimos en el bloque 2. Las variables de entorno son parámetros externos que pueden afectar el comportamiento de aplicaciones y sistemas, sin necesidad de modificar el código fuente. En el contexto de Node.js, son cruciales para la seguridad, ya que permiten almacenar información sensible, como contraseñas y claves de API, fuera del código. Esto reduce el riesgo de exposición accidental en repositorios de código y facilita la gestión de configuraciones en diferentes entornos (desarrollo, prueba, producción).

Para ello crearemos un archivo .env en la raíz de nuestro proyecto. Un ejemplo del contenido de este archivo será el siguiente:

  MONGODB_URI = mongodb+srv://username:<password>@cluster0.c9p8mzk.mongodb.net/?retryWrites=true&w=majority&appName=Cluster0

En este ejemplo, MONGO_URI es el nombre de mi variable de entorno y el valor asignado es la cadena de conexión que nos provee MongoDB Atlas. Aquí debes reemplazar el texto que dice username y por los datos del usuario y contraseña que se creó en MondoDB Atlas.

Uso de la variable de entorno en el archivo index.js

Ahora vamos a usar la variable de conexión, así que creamos una constante para traer la cadena de conexión desde el archivo .env.

  const mongoUri = process.env.MONGODB_URI;

Aquí, a través de procces.env.MONGODB_URI accedemos a la variable y podemos usar la cadena de conexión.

  try {
  mongoose.connect(mongoUri);
  console.log("Conectado a MongoDB");
  } catch (error) {
  console.error("Error de conexón", error);
  }

Obtenemos una referencia a la conexión con la base de datos para usarla más tarde.

  const db = mongoose.connection;

Creación de un esquema y modelo con mongoose

Una vez lista la conexión a la base de datos y antes de comenzar a crear las rutas, se debe crear un esquema y un modelo con mongoose. Primero se define un esquema para el modelo Libro. El esquema determina la estructura de los documentos en la colección de MongoDB, es como un plano, En este caso, cada libro tendrá un título y un autor, ambos de tipo String.

  const libroSchema = new mongoose.Schema({
    titulo: String,
    autor: String,
  });

Por último, creamos un modelo llamado Libro utilizando el esquema definido anteriormente. Con este modelo, puedes realizar operaciones CRUD sobre la colección de libros en la base de datos. Mongoose creará o utilizará una colección llamada libros (versión pluralizada del nombre del modelo) en la base de datos.

  const Libro = mongoose.model("Libro", libroSchema);

Ahora pasaremos a crear las rutas para las peticiones.

Ya tenemos todo listo para crear las rutas de nuestra API con la ayuda de Express.

Ruta raíz

Comenzamos con la ruta raíz "/", la cual agregamos igualmente en nuestro archivo principal index.js

  app.get("/", (req, res) => {
    res.send("Bienvenido a la tienda de libros");
  });

Para probar esta ruta vamos a levantar el servidor de Node con el siguiente código:

  app.listen(PORT, () => {
    console.log("Servidor ejecutándose en http://localhost:3000/");
  });

Para ello, vamos a configurar un script para que se levante el servidor, pero a través de nodemon, esto nos servirá para que cada vez que se haga un cambio en el código, el servidor sea reiniciado automáticamente y tome dichos cambios. Agregamos el script al package.json y nos quedará de la siguiente forma:

{
  "name": "nombre del proyecto",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "start": "nodemon index.js"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}

Con esto podemos ir a la terminal y ejecutar npm start, lo que levanta el servidor y deberíamos ver en el terminal el siguiente mensaje:

terminal-start

Y si visitamos en nuestro navegador la ruta http://localhost:3000/ deberíamos tener el mensaje Bienvenido a la tienda de libros, con lo que confirmamos que nuestra primera ruta / está funcionando. Lo siguiente es crear las demás rutas del CRUD

Ruta para crear un nuevo libro

En esta ruta construimos un nuevo libro con la ayuda del modelo creado con mongoose, tomamos los datos que vienen en la petición y usamos el método save para guardar el nuevo libro en la base de datos.

  app.post("/libros", async (req, res) => {
    const libro = new Libro({
      titulo: req.body.titulo,
      autor: req.body.autor,
    });

    try {
      await libro.save();
      res.json(libro);
    } catch (error) {
      res.status(500).send("Error al guardar libro");
    }
  });

Ruta para pedir todos los libros

Usando el método find en nuestro modelo Libro podemos traer el listado de todos los libros creados en la base de datos.

  app.get("/libros", async (req, res) => {
    try {
      const libros = await Libro.find();
      res.json(libros);
    } catch (error) {
      res.status(500).send("Error al obtener libros");
    }
  });

Ruta para obtener un libro específico por su ID

Usando el método findById podemos traer un libro por su ID.

  app.get("/libros/:id", async (req, res) => {
    try {
      const libro = await Libro.findById(req.params.id);
      if (libro) {
        res.json(libro);
      } else {
        res.status(404).send("Libro no encontrado");
      }
    } catch (error) {
      res.status(500).send("Error al buscar el libro");
    }
  });

Ruta para actualizar un libro específico por su ID

Usando el método findByIDAndUpdate podemos actualizar un libro por su ID

  app.put("/libros/:id", async (req, res) => {
    try {
      const libro = await Libro.findByIdAndUpdate(
        req.params.id,
        {
          titulo: req.body.titulo,
          autor: req.body.autor,
        },
        { new: true } // Esta opción hará que se devuelva el documento actualizado
      );

      if (libro) {
        res.json(libro);
      } else {
        res.status(404).send("Libro no encontrado");
      }
    } catch (error) {
      res.status(500).send("Error al actualizar el libro");
    }
  });

Ruta para eliminar un libro específico por su ID

Por último, para este ejemplo, mediante el método findByIdAndDelete podemos eliminar un libro de nuestra base de datos por su ID.

  app.delete("/libros/:id", async (req, res) => {
    try {
      const libro = await Libro.findByIdAndRemove(req.params.id);
      if (libro) {
        res.status(204).send();
      } else {
        res.status(404).send("Libro no encontrado");
      }
    } catch (error) {
      res.status(500).send("Error al eliminar el libro");
    }
  });

Con esto ya tendríamos todas las rutas necesarias para nuestro ejemplo de un CRUD de libros, si quieres ver todos los métodos que nos brinda mongoose puedes ir a su documentación en el siguiente enlace mongoose.

Para terminar vamos a usar una herramienta que nos sera muy util a la hora de probar las rutas de nuestra API. Postman es una herramienta de pruebas y desarrollo de API que permite a los desarrolladores enviar peticiones a servicios web y ver respuestas. Postman está diseñado para enviar solicitudes desde el lado del cliente al servidor web y recibir una respuesta del back-end. Para descargar esta herramienta puedes descargarla desde el siguiente enlace postman.

Una vez instalado podremos lanzar peticiones a nuestro servidor, por ejemplo una petición POST para crear un nuevo libro.

peticion-post

peticion-ruta

peticion-body

peticion-respuesta

De la misma manera puedes probar el resto de rutas, y al final tendras tu primer API creada y funcional.