Cómo usar MongoDB con Node.js

Cómo conectar una aplicación Node.js a una base de datos MongoDB existente usando Node.js.

Primeros pasos

Debido a que el código que estamos escribiendo para este tutorial es "independiente" (lo que significa que no es parte de una aplicación o proyecto más grande), vamos a crear un proyecto de Node.js desde cero. Si aún no tiene Node.js instalado en su computadora, lea este tutorial primero y luego regrese aquí.

Una vez que haya instalado Node.js en su computadora, desde la carpeta de proyectos en su computadora (por ejemplo, ~/projects ), crea una nueva carpeta para nuestro trabajo:

Terminal

mkdir mongodb-tutorial

A continuación, queremos instalar dos dependencias, mongodb y express :

Terminal

npm i mongodb express

El primero nos dará acceso al controlador Node.js para MongoDB (lo que usaremos para conectarnos a la base de datos en nuestro código) y el segundo, Express, se usará para activar un servidor de demostración.

Un último paso:en el package.json archivo que se creó para usted, asegúrese de agregar el campo "type": "module" como propiedad. Esto habilitará la compatibilidad con ESModules y nos permitirá usar el import declaraciones que se muestran en el siguiente código.

Con eso en su lugar, estamos listos para comenzar.

Instalación e inicio de MongoDB

Antes de profundizar en el código, es importante que tenga MongoDB instalado y accesible en su computadora. Si no ya tiene instalado MongoDB, siga las instrucciones para la "Edición comunitaria" para su sistema operativo aquí.

Nota :para este tutorial, solo necesita asegurarse de que MongoDB esté instalado . No necesita seguir las instrucciones para iniciar MongoDB como un servicio en segundo plano. Si comprende lo que esto significa, es más que bienvenido, pero a continuación cubriremos una forma diferente de iniciar el servidor.

Inicio de un servidor MongoDB

Antes de iniciar el servidor MongoDB, necesitamos tener un directorio accesible donde MongoDB pueda almacenar los datos que genera. Desde la raíz del proyecto que acabamos de crear en "Primeros pasos", queremos crear un directorio data y dentro de eso, queremos crear otro directorio db . Una vez que haya terminado, la estructura de su directorio debería verse así:

/mongodb-tutorial
-- /data
---- /db

Una vez que tenga esto, en una ventana de terminal, cd en la raíz de la carpeta del proyecto (mongodb-tutorial ) y ejecuta lo siguiente:

Terminal

mongod --dbpath ./data/db

Después de ejecutar esto, debería ver algunos registros de MongoDB que se detendrán después de unos segundos, lo que significa que el servidor está en funcionamiento. Nota :esto iniciará MongoDB en su puerto predeterminado 27017 . Saber eso será útil cuando conectemos la conexión MongoDB en nuestra aplicación.

Conexión del adaptador MongoDB en Node.js

Para integrar MongoDB en nuestra aplicación, lo primero y más importante que debemos hacer es configurar una conexión a MongoDB usando su paquete Node.js oficial (conocido como "controlador", un término comúnmente usado para referirse al paquete o biblioteca que se usa para conectarse a una base de datos a través del código).

/conectarAMongoDB.js

import { MongoClient } from "mongodb";

const connectToMongoDB = async (uri = '', options = {}) => {
  if (!process.mongodb) {
    const mongodb = await MongoClient.connect(uri, {
      useNewUrlParser: true,
      useUnifiedTopology: true,
      ssl: process.env.NODE_ENV === "production",
      ...options,
    });

    const db = mongodb.db('example');
    process.mongodb = db;

    return {
      db,
      Collection: db.collection.bind(db),
      connection: mongodb,
    };
  }

  return null;
};

export default await connectToMongoDB('mongodb://localhost:27017', {});

Comenzando en la parte superior de nuestro archivo, lo primero que queremos hacer es importar la exportación nombrada MongoClient del mongodb paquete que instalamos a través de NPM anteriormente. La parte de exportación "nombrada" se indica mediante llaves que envuelven el nombre de la variable, mientras que ninguna llave sugiere una exportación "predeterminada".

A continuación, queremos definir una función que se encargará de establecer la conexión con nuestra base de datos. Aquí, hemos definido una función de flecha connectToMongoDB() que toma dos argumentos:uri y options .

Aquí, uri hace referencia a la cadena de conexión de MongoDB. Este es un URI especial que MongoDB reconoce y explica dónde el controlador MongoDB puede encontrar una base de datos MongoDB en ejecución para conectarse. Para options , estas son opciones de configuración especiales que queremos pasar al controlador (por ejemplo, anulaciones de valores predeterminados u opciones no establecidas aquí en el tutorial).

Dentro de la función, primero, nos aseguramos de que no tengamos un process.mongodb existente valor. Esta es una convención estamos introducción para este tutorial. Como veremos, nuestro objetivo será hacer que nuestra base de datos MongoDB sea accesible en el objeto de proceso para que, si lo deseamos, podamos acceder a nuestra conexión MongoDB globalmente en nuestra aplicación. El beneficio de esto será que podemos "reutilizar" la misma conexión en toda nuestra aplicación, lo que reduce la tensión general en el servidor MongoDB.

Si no ya tiene un valor establecido en process.mongodb , a continuación, queremos decirle al controlador que se conecte al uri pasado junto con algunas opciones predeterminadas. Para hacer eso, llamamos a MongoClient.connect() pasando el uri (el mismo pasado a nuestro connectToMongoDB() como primer argumento) al que queremos conectarnos como primer argumento, seguido de un objeto que contiene las opciones para esa conexión como segundo argumento.

Al objeto de opciones que estamos pasando como segundo argumento, hemos pasado tres valores predeterminados:

  1. useNewUrlParser que le dice al conductor que respete el nuevo mongodb+srv:// estilo de URL de conexión.
  2. useUnifiedTopology que le dice al controlador que use la nueva "topología" más eficiente (el nombre interno de MongoDB para las partes centrales de la base de datos) que combina todas las partes importantes de la base de datos en una sola pieza.
  3. ssl que le dice a MongoDB si solo debe aceptar conexiones a través de una conexión SSL segura. Aquí, establece en true solo si el valor de process.env.NODE_ENV es "production" .

Finalmente, debajo de estos valores predeterminados, usamos la extensión de JavaScript ... operador para decir "tome las opciones pasadas y distribúyalas (o "cópielas") en el objeto que estamos pasando aquí". En otras palabras, cualquier propiedad definida en el options objeto que hemos pasado como segundo argumento a connectToMongoDB se copiará en el objeto de opciones que estamos pasando a MongoClient.connect() . Además, si desea configurar una de las tres opciones predeterminadas enumeradas anteriormente de manera diferente, este patrón sobrescribirá automáticamente los valores predeterminados si especifica un valor (por ejemplo, si configura useUnifiedTopology: false en tu options objeto, que anularía el true predeterminado versión).

A continuación, con nuestra conexión (presumiblemente) accesible en el mongodb variable que asignamos a nuestro await MongoClient.connect() llamamos a, a continuación, creamos otra variable db y asígnelo a mongodb.db('example') donde example es un nombre de base de datos arbitrario al que queremos conectarnos en nuestro servidor MongoDB (esto debe reemplazarse con el nombre de su propia base de datos).

Llamamos a esto aquí porque nos da acceso abreviado a la base de datos MongoDB a la que nos estamos conectando, lo que nos evita tener que escribir el .db('<database>') parte en cada consulta que queremos ejecutar. A continuación, después de esto, asignamos ese db valor a process.mongodb (recuerde que insinuamos esto antes). Esto ahora nos da acceso global a nuestra base de datos MongoDB en toda nuestra aplicación.

Un paso más:desde nuestra función, queremos devolver un objeto que nos dé acceso a nuestra conexión MongoDB de varias formas. Esto nos da flexibilidad en nuestro código para que no nos quedemos con un acceso limitado a la base de datos.

En ese objeto, hemos definido tres propiedades:

  1. db cual es el db variable que acabamos de crear y explicamos anteriormente.
  2. Collection que es un "truco", que nos permite crear rápidamente un identificador para una colección específica en nuestra base de datos.
  3. connection que es la conexión sin procesar que establecimos con MongoClient.connect() .

Finalmente, en la parte inferior de nuestro connectToMongoDB() función, devolvemos null si process.mongodb ya está configurado.

Una cosa más en este archivo antes de continuar. Notará que en la parte inferior del archivo, estamos agregando una exportación predeterminada de una llamada a nuestro connectToMongoDB() función. Esto es intencional. Esto nos permite establecer una conexión a MongoDB automáticamente donde sea que se importe este archivo en nuestra aplicación. Si miramos, estamos codificando el URI para nuestra base de datos MongoDB como el primer argumento pasado a la función mongodb://localhost:27017 .

Esto se pasará a connectToMongoDB() como el uri argumento y, en última instancia, convertirse en la base de datos a la que el controlador intenta conectarse. Porque usamos el async palabra clave delante de connectToMongoDB() , cuando se le llame, devolverá un objeto JavaScript Promise, por lo que, frente a nuestra llamada en la parte inferior del archivo, usamos el await palabra clave de nuevo para decir "esperar a que se establezca la conexión antes de exportar el valor".

Con eso, nuestra conexión está lista. A continuación, veremos algunos ejemplos de uso en nuestra aplicación.

Creación de una colección y datos de prueba

Primero, para demostrar nuestra conexión, necesitaremos algunos datos de prueba para que funcione. Esta es una gran oportunidad para ver cómo el Collection personalizado función que exportamos desde nuestro /connectToMongoDB.js el archivo funciona.

/libros.js

import MongoDB from './connectToMongoDB.js';

const Books = MongoDB.Collection('books');

if (await Books.countDocuments() < 3) {
  await Books.bulkWrite([
    {
      insertOne: {
        document: {
          title: 'The Culture We Deserve',
          author: 'Jacques Barzun',
          year: '1989',
        },
      },
    },
    {
      insertOne: {
        document: {
          title: 'The Fabric of Reality',
          author: 'David Deutsch',
          year: '1998',
        },
      },
    },
    {
      insertOne: {
        document: {
          title: 'The Bitcoin Standard',
          author: 'Saifedean Ammous',
          year: '2018',
        },
      },
    }
  ])
}

export default Books;

Primero, en la parte superior de nuestro archivo, importamos la exportación predeterminada del /connectToMongoDB.js archivo que escribimos arriba (el resultado de llamar a await connectToMongoDB() ). En el MongoDB variable aquí, esperamos tener el objeto que devolvimos de nuestro connectToMongoDB() función.

Recuerda que en ese objeto, agregamos una propiedad especial Collection lo que nos brinda una manera fácil de conectarnos a una colección de MongoDB con menos código. Aquí, para crear un identificador para una nueva colección books , llamamos a MongoDB.collection('books') . Esto hace dos cosas:

  1. Crea el books colección en MongoDB si aún no existe.
  2. Devuelve el identificador de la colección para su uso en otro lugar de nuestro código.

Por "mango" nos referimos a una referencia a la colección. Podemos ver este identificador puesto en uso justo debajo de esto, donde intentamos sembrar la base de datos con algunos datos de prueba. Aquí, decimos "si Books.countDocuments() devuelve un número menor que tres, inserte los siguientes documentos en esa colección".

Sin esto, tendríamos que escribir algo como...

await process.mongodb.collection('books').countDocuments();

or

MongoDB.db.collection('books').countDocuments();

Mucho más conciso gracias a nuestro Collection función.

Aunque no es muy relevante para nuestro trabajo aquí, dentro del if declaración, asumiendo que no tenemos tres libros existentes, llamamos al .bulkWrite() El método MongoDB proporciona como parte del controlador, insertando tres libros para nuestros datos de prueba.

La parte importante:en la parte inferior de nuestro archivo, tomamos el Books variable en la que almacenamos nuestro identificador de colección y lo exportamos como el valor predeterminado de nuestro archivo. Esto será útil cuando leamos algunos datos de la base de datos.

Lectura de datos

Para terminar, ahora, queremos demostrar la lectura de datos de MongoDB utilizando el identificador de colección que acabamos de establecer con MongoDB.Collection() . Para hacerlo, conectaremos una aplicación Express.js simple con una sola ruta /books donde podemos recuperar la lista actual de libros de nuestra colección.

/index.js

import express from 'express';
import Books from './books.js';

const app = express();

app.get('/books', async (req, res) => {
  res.setHeader('Content-Type', 'application/json');
  res.status(200);
  res.send(JSON.stringify({ books: await Books.find().toArray() }, null, 2));
});

app.listen(3000, () => {
  console.log('App running on localhost:3000');
});

Una descripción general rápida de las partes Express:aquí, importamos express del express paquete que instalamos anteriormente y luego creamos una nueva instancia llamando a express() como una función y almacenando esa instancia en la variable app .

A continuación, en la parte inferior de nuestro archivo, iniciamos nuestro servidor Express.js en el puerto 3000 llamando al app.listen() y proporcionando una función de devolución de llamada en la que desconectamos un mensaje en nuestro terminal para informarnos que el servidor se está ejecutando.

La parte que nos importa aquí:en el medio, hemos agregado una llamada a app.get() que define una ruta en nuestra aplicación /books que admite un HTTP GET solicitud. Para esa ruta, hemos definido una función de controlador (preste atención al uso de async delante de la función, lo que significa que usaremos await en algún lugar dentro de la función) que está diseñado para responder con una lista de nuestros libros.

Para hacerlo, nos aseguramos de configurar el Content-Type encabezado en el res poner objeto a application/json , luego proporcione un código de estado HTTP de 200 (que significa ok o success ) y finalmente, llamar al res.send() , pasando un JSON.stringify() llamada, a la que estamos pasando un objeto con una propiedad books que se asigna al resultado de llamar a await Books.find().toArray() que aprovecha el Books controlador que creamos en el paso anterior para realizar una consulta en nuestra colección de libros.

¡Eso es todo! Si nos aseguramos de que nuestra base de datos MongoDB esté funcionando y luego iniciemos este servidor con node index.js desde nuestra terminal (necesitará una ventana/pestaña de terminal para MongoDB y otra para este servidor Express), deberíamos ver nuestros libros si visitamos http://localhost:3000/books .

Terminando

En este tutorial, aprendimos cómo conectar una conexión a una base de datos MongoDB usando el mongodb oficial paquete. Aprendimos a escribir una función contenedora para ayudarnos a establecer esa conexión junto con algunos métodos convenientes para facilitar la interacción con MongoDB en nuestro código. También aprendimos cómo crear una nueva colección y sembrarla con algunos datos, así como también cómo leer datos de una colección a través de una ruta en Express.js.