¿Cómo hacer un esquema Mongo a partir de clases puras de Typescript?

TypeScript es un lenguaje de programación orientado a objetos y es un superconjunto de JavaScript y contiene todos sus elementos. Al usar TSC (compilador de TypeScript), podemos convertir código de TypeScript (archivo .ts) a JavaScript (archivo .js). Es de código abierto y su código es más fácil de leer y comprender. 

MongoDB es una base de datos basada en documentación NoSQL versátil y ampliamente utilizada. Una colección puede contener un montón de documentos. Podemos asumir una colección como una tabla en la tecnología RDBMS, pero no se requieren relaciones sólidas de entidad en la colección. Un esquema de mangosta es equivalente a una colección. Podemos mantener diferentes datos dentro de un esquema Mongoose para crear la colección en MongoDB. En este artículo, veamos cómo hacer un esquema Mongo a partir de una clase Typescript pura. La extensión del archivo Typescript es .ts y por lo general, desde proyectos de marco Angular, estamos usando clases Typescript, y veamos en detalle. Para interactuar con MongoDB, requerimos Mongoose. 

Configuración del proyecto e instalación del módulo:

Paso 1: Vamos a usar la clase Typescript, vamos a crear inicializando un proyecto usando el siguiente comando.

 yarn init (or npm init ) 

Cuando se le solicite, establezca el punto de entrada en el siguiente archivo.

src/server.ts .

Paso 2: Instale el módulo requerido usando el siguiente comando.

# Dependency to connect to create MongoDB 
# Schema and connect to mongodb
yarn add express mongoose

# Dependency to create TypeScript files, 
# Dependency to execute those files in Node
# Dependency to speed up the development
yarn add -D nodemon typescript ts-node 
    @types/express @types/mongoose @types/node

# GlobalDependencies
npm i -g typescript ts-node

package.json: nuestro archivo package.json se verá así.

{
  "name": "mongo-typescript",
  "version": "1.0.0",
  "main": "src/server.ts",
  "license": "MIT",
  "scripts": {
    "start": "node --inspect=5858 -r ts-node/register ./src/server.ts",
    "dev": "nodemon",
    "build": "tsc",
    "script": "cd src/scripts && ts-node"
  },
  "dependencies": {
    "express": "^4.17.1",
    "mongoose": "^5.9.7"
  },
  "devDependencies": {
    "@types/express": "^4.17.6",
    "@types/mongoose": "^5.7.10",
    "@types/node": "^13.11.1",
    "nodemon": "^2.0.3",
    "ts-node": "^8.8.2",
    "typescript": "^3.8.3"
  }
}

tsconfig.json: este archivo debe crearse en el directorio raíz, le indicará al compilador la ubicación de los archivos TypeScript y nos permitirá usar la sintaxis de importación/exportación de ES6.

{
  "compilerOptions": {
    "target": "es6",
    "module": "commonjs",
    "outDir": "dist",
    "sourceMap": true
  },
  "include": ["src/**/*.ts"],
  "exclude": ["node_modules", ".vscode"]
}

Conexión a la base de datos: para la conectividad de la base de datos, cree una carpeta separada usando los siguientes comandos.

mkdir src 
cd src 
mkdir database 
touch database.ts

Estructura del proyecto: Se verá así.

Ejemplo:

database.ts

import * as Mongoose from 'mongoose';
import { EmployeeModel } from './employees/employees.model';
  
let database: Mongoose.Connection;
  
export const connect = () => {
    // Add your own uri below, here my dbname is UserDB
    // and we are using the local mongodb
    const uri =
        'mongodb://localhost:27017/UserDB';
  
    if (database) {
        return;
    }
    // In order to fix all the deprecation warnings, 
    // below are needed while connecting
    Mongoose.connect(uri, {
        useNewUrlParser: true,
        useFindAndModify: true,
        useUnifiedTopology: true,
        useCreateIndex: true,
    });
  
    database = Mongoose.connection;
    // When mentioned database is available and successfully connects
    database.once('open', async () => {
        console.log('Connected to database successfully');
    });
  
    // In case of any error
    database.on('error', () => {
        console.log(`Error connecting to database. Check Whether mongoDB
        installed or you can try to give opensource Mongo Atlas database`);
    });
  
    return {
        EmployeeModel
    };
};
  
// Safer way to get disconnected
export const disconnect = () => {
    if (!database) {
        return;
    }
  
    Mongoose.disconnect();
};

server.ts

import * as express from "express";
import { connect } from "./database/database";
  
const app = express();
  
// Available port number and it should not 
// be used by other services
const port = 5002;
  
connect();
  
// To indicate the project initiated, 
// let us add console message
app.listen(port, () => {
    console.log(`Server started on http://localhost:${port}`);
});

Crear modelos

Los archivos TypeScripts son útiles para crear Mongo Schema. Se menciona como tres partes de un modelo Mongoose (esquema, métodos estáticos y métodos de instancia), la cuarta es para mantener nuestras interfaces de TypeScript y la quinta para unir todo.

Dentro de la carpeta src/database/<nombre de la colección> , creemos los modelos. Aquí <<nombre_colección> representa el nombre de la colección MongoDB. Que lo tengamos como empleados.

  • <nombre de la colección>.schema.ts: define el esquema Mongoose, que ayuda a determinar la forma de nuestros documentos MongoDB.
  • <nombre de la colección>.statics.ts: los métodos estáticos necesarios se agregan y se llaman en el propio modelo.
  • <nombre de colección>.methods.ts: métodos de instancia de nuestro modelo, funciones que se pueden llamar en instancias de modelos individuales.
  • <nombre de la colección>.types.ts: almacena los tipos que usaremos en los otros archivos.
  • <nombre de la colección>.model.ts: se utiliza para combinar todo junto.

Podemos usar el siguiente comando para crear un directorio y archivos.

# Move to scr folder and create database folder
cd src 
mkdir database 

# Move to database folder and create employees folder
cd database 
mkdir employees

# Move to employees folder and create files
cd employees 
touch employees.schema.ts employees.statics.ts 
touch employees.methods.ts employees.types.ts employees.model.ts

employees.schema.ts

// Main schema file where we can define the
// required attributes
import * as Mongoose from "mongoose";
  
const EmployeeSchema = new Mongoose.Schema({
    firstName: String,
    lastName: String,
    age: Number,
    dateOfJoining: {
        type: Date,
        default: new Date(),
    },
    lastUpdated: {
        type: Date,
        default: new Date(),
    },
    gender: String,
    department: String,
  
    // All other required attributes
    // should be given here
});
  
export default EmployeeSchema;
  • IEmployeeDocument: Inclusión de nuestros campos y otros elementos de un Documento Mongoose estándar.
  • IEmployeeModel: representación de un modelo Mongoose estándar, que contiene documentos de nuestro tipo IEmployeeDocument .

employees.types.ts

import { Document, Model } from "mongoose";
  
// These fields represent fields of collection 
// and name of the collection is Employee
export interface IEmployee {
    firstName: string;
    lastName: string;
    age: number;
    dateOfEntry?: Date;
    lastUpdated?: Date;
    gender: String;
    department: String;
}
  
export interface IEmployeeDocument extends IEmployee, Document { }
export interface IEmployeeModel extends Model<IEmployeeDocument> { }

employees.model.ts

import { model } from "mongoose";
import { IEmployeeDocument } from "./employees.types";
import EmployeeSchema from "./employees.schema";
  
export const EmployeeModel = model<IEmployeeDocument>"employee",
  EmployeeSchema
)

Cree dos métodos estáticos como se muestra a continuación:

  • findOneOrCreate: comprueba si existe una entrada y, si no, crea una nueva entrada.
  • findByAge: devuelve una array de empleados, según un rango de edad proporcionado.

Del mismo modo, podemos definir métodos que dependen del requisito, como findByGender, findByDepartment, etc., que en última instancia coinciden con nuestros requisitos.

employees.statics.ts

import { IEmployeeDocument, IEmployeeModel } from "./employees.types";
  
// Check for the existence of an entry 
// and if it is not available, create one
export async function findOneOrCreate(
    this: IEmployeeModel,
    {
        firstName,
        lastName,
        age,
        gender,
        department,
    }: {
        firstName: string; lastName: string; age: number;
        gender: string; department: string
    }
): Promise<IEmployeeDocument> {
    const employeeRecord = await this.findOne({
        firstName,
        lastName, age, gender, department
    });
    if (employeeRecord) {
        return employeeRecord;
    } else {
        return this.create({
            firstName, lastName,
            age, gender, department
        });
    }
}
  
export async function findByAge(
    this: IEmployeeModel,
    min?: number,
    max?: number
): Promise<IEmployeeDocument[]> {
    return this.find({ age: { $gte: min || 0, $lte: max || Infinity } });
}
  
// Similarly add the rest of the methods according to the requirement

employees.methods.ts

import { Document } from "mongoose";
import { IEmployeeDocument } from "./employees.types";
  
export async function setLastUpdated(
  this: IEmployeeDocument): Promise<void> {
    const now = new Date();
    if (!this.lastUpdated || this.lastUpdated < now) {
        this.lastUpdated = now;
        await this.save();
    }
}
  
export async function sameLastName(
    this: IEmployeeDocument): Promise<Document[]> {
        return this.model("employee")
            .find({ lastName: this.lastName });
}

employees.schema.ts

import * as Mongoose from "mongoose";
import { findOneOrCreate, findByAge } from "./employees.statics";
import { setLastUpdated, sameLastName } from "./employees.methods";
  
const EmployeeSchema = new Mongoose.Schema({
    firstName: String,
    lastName: String,
    age: Number,
    dateOfJoining: {
        type: Date,
        default: new Date(),
    },
    lastUpdated: {
        type: Date,
        default: new Date(),
    },
    gender: String,
    department: String,
    // All other required attributes should be given here
});
  
EmployeeSchema.statics.findOneOrCreate = findOneOrCreate;
EmployeeSchema.statics.findByAge = findByAge;
  
EmployeeSchema.methods.setLastUpdated = setLastUpdated;
EmployeeSchema.methods.sameLastName = sameLastName;
  
export default EmployeeSchema;

employees.types.ts

import { Document, Model } from "mongoose";
  
export interface IEmployee {
    firstName: string;
    lastName: string;
    age: number;
    dateOfJoining?: Date;
    lastUpdated?: Date;
    gender: String;
    department: String;
}
  
export interface IEmployeeDocument extends IEmployee, Document {
    setLastUpdated: (this: IEmployeeDocument) => Promise<void>;
    sameLastName: (this: IEmployeeDocument) => Promise<Document[]>;
}
  
export interface IEmployeeModel extends Model<IEmployeeDocument> {
    findOneOrCreate: (
        this: IEmployeeModel,
        {
            firstName,
            lastName,
            age,
            gender,
            department,
        }: { firstName: string; lastName: string; age: number; 
            gender: string; department: string; }
    ) => Promise<IEmployeeDocument>;
    findByAge: (
        this: IEmployeeModel,
        min?: number,
        max?: number
    ) => Promise<IEmployeeDocument[]>;
}

sampleEmployeeData.ts

import { EmployeeModel } from "../database/employees/employees.model";
import { connect, disconnect } from "../database/database";
  
(async () => {
    connect();
    // Via "sampleEmployeeData.ts" we can add data to Mongoose schema
    // Our schema name is employees
    const employees = [
        {
            firstName: "Rachel", lastName: "Green", age: 25,
            gender: "Female", department: "Design"
        },
        {
            firstName: "Monica", lastName: "Geller", age: 25,
            gender: "Female", department: "Catering"
        },
        {
            firstName: "Phebe", lastName: "Phebe", age: 25,
            gender: "Female", department: "Masus"
        },
        {
            firstName: "Ross", lastName: "Geller", age: 30,
            gender: "Male", department: "Paleontology"
        },
        {
            firstName: "Chandler", lastName: "Bing", age: 30,
            gender: "Male", department: "IT"
        },
        {
            firstName: "Joey", lastName: "Joey", age: 30,
            gender: "Male", department: "Dramatist"
        },
    ];
  
    try {
        for (const employee of employees) {
            await EmployeeModel.create(employee);
            console.log(`Created employee ${employee.firstName} 
            ${employee.lastName}`);
        }
  
        disconnect();
    } catch (e) {
        console.log(e);
    }
})();

Pasos para ejecutar la aplicación: Inicie el servidor usando el siguiente comando.

yarn start

El siguiente paso es que necesitamos crear las colecciones usando el esquema Mongoose. Utilice el siguiente comando para completar los datos:

yarn script sampleEmployeeData.ts

Producción:

En el shell de Mongo, podemos verificar lo mismo. En la base de datos UserDB , al consultar db.employees.find().pretty() , podemos ver el resultado:

Conclusión: los archivos Typescript son tan geniales que tienen características avanzadas de JavaScript y al usar mongoose, Express podemos crear fácilmente esquemas MongoDB usando archivos Typescript

Publicación traducida automáticamente

Artículo escrito por priyarajtt y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *