如何从纯TypeScript类创建Mongo模式
TypeScript 是一种面向对象的编程语言,它是JavaScript的超集,包含了JavaScript的所有元素。通过使用TSC(TypeScript编译器),我们可以将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的import/export语法。
{
"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}`);
});
创建模型
使用TypeScript文件可以创建Mongo Schema。它被分为三个部分:Mongoose模型(schema,静态方法和实例方法),第四部分是保存TypeScript接口,第五部分是将所有内容汇总起来。
在 src/database/ <collectionname>
文件夹下,让我们创建这些模型。这里< <collectionname>
代表MongoDB集合的名称。我们将其命名为 employees 。
- < collectionname>.schema.ts:定义Mongoose Schema,用于确定MongoDB文档的结构。
- < collectionname>.statics.ts:添加和在模型本身上调用所需的静态方法。
- < collectionname>.methods.ts:模型的实例方法,可以在单个模型实例上调用的函数。
- < collectionname>.types.ts:存储在其他文件中将使用的类型。
- < collectionname>.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
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: 包含我们的字段和其他标准Mongoose文档的元素。
- IEmployeeModel: 代表一个标准的Mongoose模型,包含我们的 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
)
按照以下方式创建两个静态方法:
- findOneOrCreate: 检查条目是否存在,如果不存在则创建新的条目。
- findByAge: 根据提供的年龄范围返回员工数组。
类似地,我们可以根据需求定义其他方法,比如findByGender、findByDepartment等,以满足我们的需求。
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);
}
})();
运行应用程序的步骤: 使用以下命令启动服务器。
yarn start
下一步是我们需要使用Mongoose模式创建集合。使用以下命令填充数据:
yarn script sampleEmployeeData.ts
输出:
结论: Typescript文件非常酷,具有JavaScript的高级功能,并且通过使用mongoose、Express,我们可以通过使用Typescript文件轻松创建MongoDB的模式。