如何从纯 Typescript 类制作 Mongo 模式?
TypeScript是一种面向对象的编程语言,它是 JavaScript 的超集并包含其所有元素。通过使用 TSC(TypeScript Compiler),我们可以将 Typescript 代码(.ts 文件)转换为 JavaScript(.js 文件)。它是开源的,其代码更易于阅读和理解。
MongoDB是一个通用的、广泛使用的基于 NoSQL 文档的数据库。一个集合可以容纳一堆文档。我们可以将集合假设为 RDBMS 技术中的表,但集合中不需要强实体关系。 mongoose模式相当于一个集合。我们可以在Mongoose模式中保存不同的数据,以在 MongoDB 中创建集合。在本文中,让我们看看如何从纯 Typescript 类制作 Mongo 模式。 Typescript 文件的扩展名为 .ts,通常,在 Angular 框架项目中,我们使用的是 Typescript 类,让我们详细了解一下。为了与 MongoDB 交互,我们需要Mongoose。
项目设置和模块安装:
第 1 步:我们将使用 Typescript 类,让我们通过使用以下命令初始化项目来创建。
yarn init (or npm init )
出现提示时,将入口点设置为以下文件。
src/server.ts .
第 2 步:使用以下命令安装所需的模块。
# 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:我们的package.json文件将如下所示。
{
"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:这个文件必须在根目录下创建,它会告诉编译器 TypeScript 文件的位置,它允许我们使用 ES6 导入/导出语法。
{
"compilerOptions": {
"target": "es6",
"module": "commonjs",
"outDir": "dist",
"sourceMap": true
},
"include": ["src/**/*.ts"],
"exclude": ["node_modules", ".vscode"]
}
连接到数据库:对于数据库连接,使用以下命令创建一个单独的文件夹。
mkdir src
cd src
mkdir database
touch database.ts
项目结构:它看起来像这样。
例子:
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}`);
});
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;
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 { }
employees.model.ts
import { model } from "mongoose";
import { IEmployeeDocument } from "./employees.types";
import EmployeeSchema from "./employees.schema";
export const EmployeeModel = model"employee",
EmployeeSchema
)
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 {
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 {
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 {
const now = new Date();
if (!this.lastUpdated || this.lastUpdated < now) {
this.lastUpdated = now;
await this.save();
}
}
export async function sameLastName(
this: IEmployeeDocument): Promise {
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;
sameLastName: (this: IEmployeeDocument) => Promise;
}
export interface IEmployeeModel extends Model {
findOneOrCreate: (
this: IEmployeeModel,
{
firstName,
lastName,
age,
gender,
department,
}: { firstName: string; lastName: string; age: number;
gender: string; department: string; }
) => Promise;
findByAge: (
this: IEmployeeModel,
min?: number,
max?: number
) => Promise;
}
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);
}
})();
服务器.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}`);
});
创建模型
Typescript 文件有助于创建 Mongo Schema。它被称为Mongoose模型的三个部分(模式、静态方法和实例方法),第四部分是保存我们的 TypeScript 接口,第五部分是把所有东西放在一起。
在src/database/
-
.schema.ts: 定义Mongoose Schema,这有助于确定 MongoDB 文档的形状。 -
.statics.ts: 在模型本身上添加和调用所需的静态方法。 -
.methods.ts: 我们模型的实例方法,可以在单个模型实例上调用的函数。 -
.types.ts: 存储我们将在其他文件中使用的类型。 -
.model.ts: 用于将所有内容组合在一起。
我们可以使用以下命令来创建目录和文件。
# 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
雇员.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:包含我们的字段和标准Mongoose文档的其他元素。
- IEmployeeModel:标准Mongoose模型的表示,包含我们的IEmployeeDocument类型的文档。
雇员.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 { }
雇员.model.ts
import { model } from "mongoose";
import { IEmployeeDocument } from "./employees.types";
import EmployeeSchema from "./employees.schema";
export const EmployeeModel = model"employee",
EmployeeSchema
)
创建两个静态方法,如下所示:
- findOneOrCreate:检查条目是否存在,如果不存在,则创建一个新条目。
- findByAge:根据提供的年龄范围返回一组员工。
同样,我们可以根据需求定义方法,如 findByGender、findByDepartment 等,最终符合我们的需求
雇员.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 {
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 {
return this.find({ age: { $gte: min || 0, $lte: max || Infinity } });
}
// Similarly add the rest of the methods according to the requirement
员工方法.ts
import { Document } from "mongoose";
import { IEmployeeDocument } from "./employees.types";
export async function setLastUpdated(
this: IEmployeeDocument): Promise {
const now = new Date();
if (!this.lastUpdated || this.lastUpdated < now) {
this.lastUpdated = now;
await this.save();
}
}
export async function sameLastName(
this: IEmployeeDocument): Promise {
return this.model("employee")
.find({ lastName: this.lastName });
}
雇员.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;
雇员.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;
sameLastName: (this: IEmployeeDocument) => Promise;
}
export interface IEmployeeModel extends Model {
findOneOrCreate: (
this: IEmployeeModel,
{
firstName,
lastName,
age,
gender,
department,
}: { firstName: string; lastName: string; age: number;
gender: string; department: string; }
) => Promise;
findByAge: (
this: IEmployeeModel,
min?: number,
max?: number
) => Promise;
}
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);
}
})();
运行应用程序的步骤:使用以下命令启动服务器。
yarn start
下一步是我们需要使用Mongoose模式创建集合。使用以下命令填写数据:
yarn script sampleEmployeeData.ts
输出:
在 Mongo shell 中,我们可以进行相同的验证。在UserDB数据库中,查询db.employees.find().pretty() ,我们可以看到输出:
结论: Typescript 文件非常酷,它具有 JavaScript 的高级功能,并且通过使用mongoose,Express 我们可以使用 Typescript 文件轻松创建 MongoDB 模式