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

相关推荐
San813_LDD31 分钟前
[C语言]《Dev-C++ 报错解决手册(Day0607 精华版)》
java·前端·javascript
xiaofeichaichai6 小时前
Webpack
前端·webpack·node.js
GetcharZp7 小时前
GitHub 49K+ Star!C++ 开发者必知的 JSON 神级库:从零到精通全指北
后端
问心无愧05137 小时前
ctf show web入门111
android·前端·笔记
xujinwei_gingko7 小时前
SpringBoot整合WebSocket
spring boot·后端·websocket
唐某人丶7 小时前
模型越来越强,我们还需要 Agent 工程吗?—— 从价值重估到 Harness 实践
前端·agent·ai编程
智码看视界7 小时前
现代Web开发基础:全栈工程师的起航点
前端·后端·c5全栈
程序员cxuan7 小时前
Claude Fable 5 来了
人工智能·后端·程序员
JS菌7 小时前
手写一个 AI Agent 全栈项目:从沙箱执行到子智能体的完整实现
前端·人工智能·后端