在NestJs中连接MongoDB如何快速生成Schema,别再全部手写了😁😁😁

最近在开发一个后端项目,需要从另外一个后台语言转换成 NestJs 的,后端数据库使用的是 MongoDB。

背景

在使用的时候就遇到了一个问题,使用 MongoDB 会需要定义大量的 schema 配置才能做完成一个表的使用,并且类型也多,于是我想到了实现一个工具来对已有的返回数据对其进行初始化,然后生成一个初始的 schema,然后对其进行修改完善。

具体实现

假设我们有一个后台接口返回的数据是以下结构:

json 复制代码
{
  "name": "string",
  "age": {
    "type": "number",
    "required": true,
    "min": 0
  },
  "gender": {
    "type": "enum",
    "values": ["male", "female", "non-binary", "prefer not to say"]
  },
  "address": {
    "street": "string",
    "city": "string",
    "country": "string"
  },
  "friends": [
    {
      "name": "string"
    }
  ]
}

数据我们有了,接下来我们创建一个node项目来编写相关的脚本,安装相关依赖:

bash 复制代码
npm i mongoose

之后在根目录下创建一个 index.js 文件并编写一下代码:

js 复制代码
const fs = require("fs");

function generateSchemaClass(
  jsonSchema,
  className,
  generatedClasses = [],
  isSubClass = false
) {
  let tsCode = "";

  if (!isSubClass) {
    tsCode = `
import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
import { HydratedDocument } from 'mongoose';
`;
  }

  tsCode += `
@Schema()
export class ${className} {
`;

  for (const [key, value] of Object.entries(jsonSchema)) {
    if (Array.isArray(value)) {
      const typeName = capitalize(key.slice(0, -1));

      if (!generatedClasses.includes(typeName)) {
        tsCode += generateSchemaClass(
          value[0],
          typeName,
          generatedClasses,
          true
        );
        generatedClasses.push(typeName);
      }
      jsonSchema[key] = [{ type: typeName }];
    }
  }

  for (const [key, value] of Object.entries(jsonSchema)) {
    if (typeof value === "string") {
      tsCode += `
  @Prop()
  ${key}: ${value};
`;
    } else if (value.type === "enum") {
      tsCode += `
  @Prop()
  ${key}: ${value.values.join(" | ")};
`;
    } else if (value.type) {
      tsCode += `
  @Prop(${value.required ? "{ required: true }" : ""})
  ${key}: ${value.type};
`;
    } else if (Array.isArray(value)) {
      tsCode += `
  @Prop([{ type: () => ${value[0].type} }])
  ${key}: ${value[0].type}[];
`;
    }
  }

  tsCode += `}
export const ${className.toLowerCase()}Schema = SchemaFactory.createForClass(${className});
export type ${className}Document = HydratedDocument<${className}>;
`;

  return tsCode;
}

function capitalize(str) {
  return str.charAt(0).toUpperCase() + str.slice(1);
}

const jsonSchema = JSON.parse(fs.readFileSync("./index.json", "utf-8"));
const className = "Models";
const tsCode = generateSchemaClass(jsonSchema, className);
fs.writeFileSync("./path-to-output.ts", tsCode);

在上面的代码中,主要有以下步骤,如下所示

  1. 使用 Node.js 的 fs 模块用于文件的读取和写入。

  2. 创建一个主要用于生成 TypeScript 类定义的 generateSchemaClass 函数。

  3. 如果不是生成子类,则将 NestJS 和 Mongoose 的导入语句添加到生成的代码字符串中。

  4. 如果是子类,则生成一个带有 @Schema() 装饰器的类定义。

  5. 处理数组类型属性有以下步骤:

    • 对 JSON Schema 进行迭代,找出数组类型的属性。
    • 对每个数组类型的属性生成一个子类定义,并更新该属性的类型信息。
  6. 继续遍历 JSON Schema,并根据属性的类型添加相应的 @Prop 装饰器和类型定义。

  7. 将类的结束括号、SchemaFactory 创建语句和导出类型添加到代码字符串中。

  8. 实现一个 capitalize 函数用于将字符串首字母大写的辅助函数。

  9. 使用 fs 模块读取 JSON 文件,并将其内容解析为一个 JavaScript 对象。

  10. 调用 generateSchemaClass 函数,传入解析后的 JSON Schema 和目标类名,生成 TypeScript 代码。

  11. 将生成的 TypeScript 代码字符串写入到一个指定的 .ts 文件中。

通过递归生成主类和可能的子类定义,它能够处理嵌套的对象和数组类型属性。处理的结果是一个或多个装饰过的 TypeScript 类,可以在 NestJS 项目中用作 Mongoose 模型的定义。通过这种方式能够实现从数据模型到代码的自动转换,提高了开发效率并减少了手动编写模型定义时可能出现的错误。

总结

在日常开发的过程中,我们难免会遇到一些重复的工作,这个时候,我们就可以去想到实现一些工作来帮助我们去处理一下重复的工作,以提升工作效率了

最后分享两个我的两个开源项目,它们分别是:

这两个项目都会一直维护的,如果你也喜欢,欢迎 star 🚗🚗🚗

相关推荐
00后程序员7 分钟前
如何解决浏览器HTTPS不安全连接警告及SSL证书问题
后端
00后程序员7 分钟前
苹果App上架审核延迟7工作日无反应:如何通过App Store Connect和邮件询问进度
后端
小猪努力学前端8 分钟前
基于PixiJS的小游戏广告开发
前端·webgl·游戏开发
DS小龙哥9 分钟前
基于物联网设计的蜂箱智能监测系统设计
后端
哆啦A梦158813 分钟前
62 对接支付宝沙箱
前端·javascript·vue.js·node.js
QZQ5418814 分钟前
C++编译期计算
后端
饕餮争锋18 分钟前
Spring内置的Bean作用域介绍
java·后端·spring
CryptoRzz19 分钟前
美股 (US) 与 墨西哥 (Mexico) 股票数据接口集成指南
后端
Tzarevich24 分钟前
用 OOP 思维打造可复用的就地编辑组件:EditInPlace 实战解析
javascript·前端框架
用户81686947472525 分钟前
Lane 优先级模型与时间切片调度
前端·react.js