por Nick Karnik

Mongoose es una biblioteca de modelado de datos de objetos (ODM) para MongoDB y Node.js. Gestiona las relaciones entre datos, proporciona validación de esquemas y se utiliza para traducir entre objetos en código y la representación de esos objetos en MongoDB.

mapeo de objetos entre el nodo y MongoDB administrado a través de Mongoose

MongoDB es una base de datos de documentos NoSQL sin esquema., Significa que puede almacenar documentos JSON en él, y la estructura de estos documentos puede variar, ya que no se aplica como las bases de datos SQL. Esta es una de las ventajas de usar NoSQL, ya que acelera el desarrollo de aplicaciones y reduce la complejidad de las implementaciones.

a continuación se muestra un ejemplo de cómo se almacenan los datos en la base de datos Mongo vs. SQL:

documentos NoSQL vs., Tablas relacionales en SQL

terminologías

colecciones

‘colecciones’ en Mongo son equivalentes a tablas en bases de datos relacionales. Pueden contener varios documentos JSON.

Documents

‘Documents’ son equivalentes a registros o filas de datos en SQL. Mientras que una fila SQL puede hacer referencia a datos en otras tablas, los documentos Mongo generalmente los combinan en un documento.

Fields

Los’ campos ‘ o atributos son similares a las columnas de una tabla SQL.

Schema

mientras Mongo no tiene esquema, SQL define un esquema a través de la definición de tabla., Un ‘esquema’ de mangosta es una estructura de datos del documento (o forma del documento) que se aplica a través de la capa de aplicación.

Models

Los’ Models ‘ son constructores de orden superior que toman un esquema y crean una instancia de un documento equivalente a registros en una base de datos relacional.

Introducción

instalación de Mongo

antes de empezar, vamos a configurar Mongo., Puede elegir entre una de las siguientes opciones (estamos utilizando la opción #1 para este artículo):

  1. descargue la versión apropiada de MongoDB para su sistema operativo desde el Sitio Web de MongoDB y siga sus instrucciones de instalación
  2. Crear una suscripción gratuita a la base de datos sandbox en mLab
  3. instalar Mongo usando Docker si prefiere usar docker

naveguemos a través de algunos de los conceptos básicos de Mongoose implementando un modelo que representa datos para una libreta de direcciones simplificada.

estoy usando Visual Studio Code, Node 8.9 y NPM 5.6., Enciende tu IDE favorito, crea un proyecto en blanco y ¡comencemos! Usaremos la sintaxis limitada ES6 en Node, por lo que no configuraremos Babel.

npm Install

vayamos a la carpeta del proyecto e inicialicemos nuestro proyecto

npm init -y

instalemos Mongoose y una biblioteca de validación con el siguiente comando:

npm install mongoose validator

el comando install anterior instalará la última versión de las bibliotecas. La sintaxis de Mangosta en este artículo es específica de Mangosta v5 y más allá.,

conexión a la base de datos

crear un archivo ./src/database.js en la raíz del proyecto.

a continuación, agregaremos una clase simple con un método que se conecta a la base de datos.

su cadena de conexión variará en función de su instalación.

la llamada require(‘mongoose’) devuelve un objeto Singleton. Significa que la primera vez que llame a require(‘mongoose’), está creando una instancia de la clase Mongoose y regresándola., En llamadas posteriores, devolverá la misma instancia que se creó y le devolvió la primera vez debido a cómo funciona la importación/exportación de módulos en ES6.

Module import/require work-flow

del mismo modo, hemos convertido nuestra clase de base de datos en un singleton devolviendo una instancia de la clase en la instrucción module.exports porque solo necesitamos una sola conexión a la base de datos.,

es6 hace que sea muy fácil para nosotros crear un patrón singleton (instancia única) debido a cómo funciona el cargador de Módulos al almacenar en caché la respuesta de un archivo importado previamente.

esquema de Mangosta vs. modelo

un modelo de mangosta es un envoltorio en el esquema de Mangosta. Un esquema Mongoose define la estructura del documento, valores por defecto, validadores, etc., mientras que un modelo de Mangosta proporciona una interfaz a la base de datos para crear, consultar, actualizar, eliminar registros, etc.

crear un modelo de Mangosta consta principalmente de tres partes:

1., Referencia Mongoose

let mongoose = require('mongoose')

Esta referencia será la misma que se devolvió cuando nos conectamos a la base de datos, lo que significa que las definiciones de esquema y modelo no necesitarán conectarse explícitamente a la base de datos.

2. Definición del esquema

un esquema define las propiedades del documento a través de un objeto en el que el nombre de la clave corresponde al nombre de la propiedad de la colección.,

let emailSchema = new mongoose.Schema({ email: String})

aquí definimos una propiedad llamada email con una cadena de tipo esquema que se asigna a un validador interno que se activará cuando el modelo se guarde en la base de datos. Fallará si el tipo de datos del valor no es un tipo de cadena.

Los siguientes Tipos de Esquemas son permitidas:

  • Array
  • Boolean
  • Buffer
  • Fecha
  • Mixtos (genérico / flexible tipo de datos)
  • Número
  • ObjectId
  • String

Mezclado y ObjectId se define en require(‘mongoose’).Schema.Types.

3., Exportando un modelo

necesitamos llamar al constructor del modelo en la instancia de Mongoose y pasarle el nombre de la colección y una referencia a la definición del esquema.

module.exports = mongoose.model('Email', emailSchema)

combinemos el código anterior en ./src/models/email.js para definir el contenido de un modelo de correo electrónico básico:

una definición de esquema debe ser simple, pero su complejidad generalmente se basa en los requisitos de la aplicación. Los esquemas se pueden reutilizar y también pueden contener varios esquemas secundarios. En el ejemplo anterior, el valor de la propiedad email es un tipo de valor simple., Sin embargo, también puede ser un tipo de objeto con propiedades adicionales.

podemos crear una instancia del modelo que definimos anteriormente y rellenarla utilizando la siguiente sintaxis:

let EmailModel = require('./email')let msg = new EmailModel({ email: '[email protected]'})

vamos a mejorar el esquema de correo electrónico para hacer que la propiedad de correo electrónico sea un campo único y obligatorio y convertir el valor a minúsculas antes de guardarlo. También podemos agregar una función de validación que asegurará que el valor sea una dirección de correo electrónico válida. Haremos referencia y usaremos la biblioteca validadora instalada anteriormente.,

operaciones básicas

Mongoose tiene una API flexible y proporciona muchas formas de realizar una tarea. No nos centraremos en las variaciones porque eso está fuera del alcance de este artículo, pero recuerde que la mayoría de las operaciones se pueden hacer de más de una manera, ya sea sintácticamente o a través de la arquitectura de la aplicación.,

Crear registro

vamos a crear una instancia del modelo de correo electrónico y guardarlo en la base de datos:

el resultado es un documento que se devuelve al guardar correctamente:

{ _id: 5a78fe3e2f44ba8f85a2409a, email: '[email protected]', __v: 0 }

se devuelven los siguientes campos (los campos internos tienen el prefijo de un guion bajo):

  1. El _id el campo se genera automáticamente por Mongo y es una clave principal de la colección. Su valor es un identificador único para el documento.
  2. Se devuelve el valor del campo email., Tenga en cuenta que está en un caso inferior porque especificamos el atributo lowercase:true en el esquema.
  3. __v es la propiedad versionKey establecida en cada documento cuando fue creado por primera vez por Mongoose. Su valor contiene la revisión interna del documento.

si intenta repetir la operación de guardado anterior, obtendrá un error porque hemos especificado que el campo de correo electrónico debe ser único.

Fetch Record

intentemos recuperar el registro que guardamos anteriormente en la base de datos., La clase model expone varios métodos estáticos y de instancia para realizar operaciones en la base de datos. Ahora intentaremos encontrar el registro que creamos previamente usando el método find y pasaremos el correo electrónico como el término de búsqueda.

EmailModel .find({ email: '[email protected]' // search query }) .then(doc => { console.log(doc) }) .catch(err => { console.error(err) })

el documento devuelto será similar a lo que se mostró cuando creamos el registro:

{ _id: 5a78fe3e2f44ba8f85a2409a, email: '[email protected]', __v: 0 }

Actualizar registro

Modifiquemos el registro anterior cambiando la dirección de correo electrónico y agregándole otro campo, todo en una sola operación., Por razones de rendimiento, Mongoose no devolverá el documento actualizado, por lo que necesitamos pasar un parámetro adicional para solicitarlo:

el documento devuelto contendrá el correo electrónico actualizado:

{ _id: 5a78fe3e2f44ba8f85a2409a, email: '[email protected]', __v: 0 }

Eliminar registro

usaremos la llamada findOneAndRemove para eliminar un registro., Devuelve el documento original que se eliminó:

Helpers

hemos analizado algunas de las funciones básicas anteriores conocidas como operaciones CRUD (Create, Read, Update, Delete), pero Mongoose también proporciona la capacidad de configurar varios tipos de métodos y propiedades helper. Estos se pueden utilizar para simplificar aún más el trabajo con datos.

vamos a crear un esquema de usuario en ./src/models/user.js con los camposfirstName y lastName:

propiedad Virtual

una propiedad virtual no se conserva en la base de datos., Podemos añadirlo a nuestro esquema como ayudante para obtener y establecer valores.

vamos a crear una propiedad virtual llamada fullName que se puede utilizar para establecer valores en firstName y lastName y recuperarlos como un valor combinado cuando se lee:

Las devoluciones de llamada para get y set deben usar la palabra clave function ya que necesitamos modele a través de la palabra clave this. El uso de las funciones de flecha fat cambiará a lo que this se refiere.,

ahora, podemos establecer firstName y lastName asignando un valor a fullName:

el código anterior generará lo siguiente:

{ _id: 5a7a4248550ebb9fafd898cf, firstName: 'Thomas', lastName: 'Anderson' } Thomas Anderson

instance methods

podemos crear métodos auxiliares personalizados en el esquema y acceder a ellos a través de la instancia del modelo. Estos métodos tendrán acceso al objeto modelo y se pueden usar de manera bastante creativa. Por ejemplo, podríamos crear un método para encontrar a todas las personas que tienen el mismo nombre que la instancia actual.,

en este ejemplo, vamos a crear una función para devolver las iniciales del usuario actual. Agreguemos un método auxiliar personalizado llamado getInitials al esquema:

userSchema.methods.getInitials = function() { return this.firstName + this.lastName}

Este método será accesible a través de una instancia de modelo:

métodos estáticos

Similar a los métodos de instancia, podemos crear métodos estáticos en el esquema., Vamos a crear un método para recuperar todos los usuarios en la base de datos:

llamando a getUsers en la clase modelo devolverá todos los usuarios en la base de Datos:

UserModel.getUsers() .then(docs => { console.log(docs) }) .catch(err => { console.error(err) })

agregar instancia y métodos estáticos es un buen enfoque para implementar una interfaz para las interacciones de la base de datos en colecciones y registros.

Middleware

Middleware son funciones que se ejecutan en etapas específicas de una canalización., Mongoose soporta middleware para las siguientes operaciones:

  • Aggregate
  • Document
  • Model
  • Query

por ejemplo, los modelos tienen pre y post funciones que toman dos parámetros:

  1. type of event (‘INIT’, ‘validate’, ‘save’, ‘remove’)
  2. Una devolución de llamada que se ejecuta con esta referencia a la instancia del modelo
ejemplo de middleware (también conocido como, pre y post ganchos)

intentemos un ejemplo mediante la adición de dos campos llamados createdAt y updatedAt para nuestro esquema:

Cuando model.save() se llama, hay un pre(‘save’, …) y post(‘save’, …) evento que se dispara. Para el segundo parámetro, puede pasar una función que se llama cuando se activa el evento. Estas funciones llevan un parámetro a la siguiente función en la cadena de middleware.,

vamos a añadir un gancho de pre-guardar y establecer valores para createdAt y updatedAt:

vamos a crear y guardar nuestro modelo:

debería ver valores para createdAt y updatedAt cuando se imprime el registro que se crea:

plugins

supongamos que queremos rastrear cuándo se creó un registro y se actualizó por última vez en cada colección de nuestra base de datos. En lugar de repetir el proceso anterior, podemos crear un plugin y aplicarlo a cada esquema.,

vamos a crear un archivo ./src/model/plugins/timestamp.js y replicar la funcionalidad anterior como un módulo reutilizable:

para usar este plugin, simplemente lo pasamos a los esquemas a los que se les debe dar esta funcionalidad:

Query Building

Mongoose tiene una API muy rica que maneja muchas operaciones complejas soportadas por MongoDB. Considere una consulta donde podemos construir componentes de consulta de forma incremental.,

en este ejemplo, vamos a:

  1. Buscar todos los usuarios
  2. saltar los primeros 100 registros
  3. limitar los resultados a 10 registros
  4. ordenar los resultados por el campo firstName
  5. Seleccionar el firstName
  6. ejecutar esa consulta

Cerrar

apenas hemos arañado la superficie explorando algunas de las de mangosta. Es una rica biblioteca llena de características útiles y poderosas que hacen que sea una alegría trabajar con modelos de datos en la capa de aplicación.,

mientras que puedes interactuar con Mongo directamente usando el controlador Mongo, Mongoose simplificará esa interacción al permitirte modelar relaciones entre datos y validarlas fácilmente.

dato curioso: mangosta es creado por Valeri Karpov que es un ingeniero increíblemente talentoso! Él acuñó el término la pila Media.

si este artículo fue útil, ??? y Sígueme en Twitter.

también Te puede gustar mi taller en youtube: Cómo Construir una API REST con Node | Express | Mongo