在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 🚗🚗🚗

相关推荐
摇滚侠1 小时前
《SpringBoot 3:入门与应用实战》第 14 章 打包与部署 Spring Boot 应用打包 阅读笔记 41
spring boot·笔记·后端
leoZ2311 小时前
第 6 篇:SchemaForm 渲染器核心实现
前端·javascript·vue.js·人工智能·神经网络·机器学习·自然语言处理
CoderYanger1 小时前
前端基础——JavaScript(基础语法)(下篇)
java·开发语言·前端·javascript·程序人生·面试·职场和发展
还是大剑师兰特2 小时前
vue项目浏览器版本判别,低于IE11跳转到新页面
前端·javascript·vue.js
计算机魔术师2 小时前
奥尔特曼致歉 GPT-6 Astra 发布混乱,现已面向所有 Plus / Pro 等用户推出
前端
落樱弥城2 小时前
RHI 设计考量:不同 API 差异分析
服务器·前端·性能优化
热心网友俣先生2 小时前
2026国赛C题:五年命题规律与预测
java·c语言·前端·数学建模
想吃火锅10052 小时前
【leetcode】42.接雨水js
开发语言·javascript·ecmascript
阿拉斯攀登3 小时前
MQ消息积压问题排查:消费卡顿、堆积、消费速度优化
后端
阿拉斯攀登3 小时前
无人售货机库存异步更新方案:解决高并发下单库存卡顿问题
后端