From 3caee6c45b01b5677ae9b77daf79c1201eb8e1b0 Mon Sep 17 00:00:00 2001 From: Lyda <1829913225@qq.com> Date: Sat, 31 Jan 2026 19:19:02 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=20mongoose=20?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E5=BA=93=E6=A8=A1=E5=9E=8B=20JS=20=E8=A7=84?= =?UTF-8?q?=E8=8C=83=E6=96=87=E6=A1=A3,=E5=B9=B6=E6=9B=B4=E6=96=B0?= =?UTF-8?q?=E5=9F=BA=E7=A1=80=E8=A7=84=E8=8C=83=E4=B8=AD=E7=9A=84=E5=B8=B8?= =?UTF-8?q?=E9=87=8F=E5=91=BD=E5=90=8D=E6=A3=80=E6=9F=A5=E8=AF=B4=E6=98=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- references/js&ts.base.md | 2 + references/js.models.md | 322 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 324 insertions(+) create mode 100644 references/js.models.md diff --git a/references/js&ts.base.md b/references/js&ts.base.md index 840e672..f82ae98 100644 --- a/references/js&ts.base.md +++ b/references/js&ts.base.md @@ -4,6 +4,8 @@ ## 常量名使用大写加下划线命名(UPPER_CASE),单词间以下划线分隔 `[JsTs.Base.ConstUpperCase]` +- 不检查 nodejs 的导包定义,比如 `const fs = require("fs")` + ### Good ```javascript diff --git a/references/js.models.md b/references/js.models.md new file mode 100644 index 0000000..d42e4c0 --- /dev/null +++ b/references/js.models.md @@ -0,0 +1,322 @@ +# mongoose 数据库模型 JS 规范 `[Js.Model]` + +> - includes `models/*.js` + +## 模型文件命名规范 `[Js.Model.FileName]` + +- 文件名使用小写加下划线命名(如 `user_extends.js`),或者使用小写加横线命名(如 `user-extends.js`) +- 文件名应与模型名称对应 + +### Good + +```txt +user.js +user_extends.js +user-profile.js +``` + +### Bad + +```txt +User.js +userExtends.js +UserProfile.js +``` + +## Schema 字段命名规范 `[Js.Model.FieldName]` + +- 字段名使用小写加下划线命名(snake_case) +- 避免使用驼峰命名 +- 要补充字段注释 +- 要补充字段类型 + +### Good + +```javascript +const userSchema = new Schema({ + user_name: { type: String }, + created_at: { type: Date }, + is_active: { type: Boolean }, +}); +``` + +### Bad + +```javascript +const userSchema = new Schema({ + userName: { type: String }, + createdAt: { type: Date }, + isActive: { type: Boolean }, +}); +``` + +## Schema 定义规范 `[Js.Model.SchemaDefinition]` + +- 必须为每个字段指定类型 +- 必要时添加 `required`、`default` 等属性 +- 复杂类型应使用嵌套 Schema 或引用 + +### Good + +```javascript +const userSchema = new Schema({ + user_name: { type: String, required: true }, + email: { type: String, required: true, unique: true }, + age: { type: Number, default: 0 }, + status: { type: String, enum: ["active", "inactive"], default: "active" }, + created_at: { type: Date, default: Date.now }, +}); +``` + +### Bad + +```javascript +const userSchema = new Schema({ + user_name: String, + email: String, + age: Number, + status: String, + created_at: Date, +}); +``` + +## 索引定义规范 `[Js.Model.IndexDefinition]` + +- 需要添加注释说明索引用途 +- 不能在 Schema 定义中直接添加索引,添加到索引要注释掉 + +### Good + +```javascript +const orderSchema = new Schema({ + user_id: { type: Schema.Types.ObjectId, ref: "User" }, + order_no: { type: String }, + created_at: { type: Date }, +}); + +// 用户订单查询索引 +// orderSchema.index({ user_id: 1, created_at: -1 }); +// 订单号唯一索引 +// orderSchema.index({ order_no: 1 }, { unique: true }); +``` + +### Bad + +```javascript +const orderSchema = new Schema({ + user_id: { type: Schema.Types.ObjectId, ref: "User", index: true }, + order_no: { type: String, index: true }, + created_at: { type: Date, index: true }, +}); +``` + +## 虚拟字段规范 `[Js.Model.VirtualField]` + +- 虚拟字段命名使用小写加下划线 +- 虚拟字段应在 Schema 定义后声明 +- 需要添加注释说明虚拟字段用途 + +### Good + +```javascript +const userSchema = new Schema({ + first_name: { type: String }, + last_name: { type: String }, +}); + +// 完整姓名虚拟字段 +userSchema.virtual("full_name").get(function () { + return this.first_name + " " + this.last_name; +}); +``` + +### Bad + +```javascript +const userSchema = new Schema({ + first_name: { type: String }, + last_name: { type: String }, + full_name: { type: String }, // 不应该存储可计算的字段 +}); +``` + +## 中间件/钩子规范 `[Js.Model.Middleware]` + +- 中间件应在 Schema 定义后、模型导出前声明 +- 需要添加注释说明中间件用途 +- 避免在中间件中执行耗时操作 + +### Good + +```javascript +const userSchema = new Schema({ + password: { type: String }, + updated_at: { type: Date }, +}); + +// 保存前更新时间戳 +userSchema.pre("save", function (next) { + this.updated_at = new Date(); + next(); +}); + +// 保存前加密密码 +userSchema.pre("save", async function (next) { + if (this.isModified("password")) { + this.password = await bcrypt.hash(this.password, 10); + } + next(); +}); +``` + +### Bad + +```javascript +const userSchema = new Schema({ + password: { type: String }, +}); + +userSchema.pre("save", function (next) { + // 没有注释说明用途 + this.password = bcrypt.hashSync(this.password, 10); // 使用同步方法阻塞 + next(); +}); +``` + +## 静态方法规范 `[Js.Model.StaticMethod]` + +- 静态方法命名使用小驼峰 +- 静态方法应在 Schema 定义后声明 +- 需要添加注释说明方法用途 + +### Good + +```javascript +const userSchema = new Schema({ + email: { type: String }, + status: { type: String }, +}); + +// 根据邮箱查找用户 +userSchema.statics.findByEmail = function (email) { + return this.findOne({ email: email }); +}; + +// 查找所有活跃用户 +userSchema.statics.findActiveUsers = function () { + return this.find({ status: "active" }); +}; +``` + +### Bad + +```javascript +const userSchema = new Schema({ + email: { type: String }, +}); + +userSchema.statics.find_by_email = function (email) { + // 方法名不应使用下划线 + return this.findOne({ email: email }); +}; +``` + +## 实例方法规范 `[Js.Model.InstanceMethod]` + +- 实例方法命名使用小驼峰 +- 实例方法应在 Schema 定义后声明 +- 需要添加注释说明方法用途 +- 实例方法内部使用 `this` 访问文档属性 + +### Good + +```javascript +const userSchema = new Schema({ + password: { type: String }, + login_count: { type: Number, default: 0 }, +}); + +// 验证密码 +userSchema.methods.comparePassword = async function (candidatePassword) { + return bcrypt.compare(candidatePassword, this.password); +}; + +// 增加登录次数 +userSchema.methods.incrementLoginCount = function () { + this.login_count += 1; + return this.save(); +}; +``` + +### Bad + +```javascript +const userSchema = new Schema({ + password: { type: String }, +}); + +userSchema.methods.compare_password = function (candidatePassword) { + // 方法名不应使用下划线 + return bcrypt.compareSync(candidatePassword, this.password); +}; +``` + +## 关联引用规范 `[Js.Model.Reference]` + +- 引用字段使用 `_id` 后缀命名 +- 必须指定 `ref` 属性 +- 需要添加注释说明关联关系 + +### Good + +```javascript +const orderSchema = new Schema({ + // 关联用户 + user_id: { type: Schema.Types.ObjectId, ref: "User", required: true }, + // 关联商品列表 + product_ids: [{ type: Schema.Types.ObjectId, ref: "Product" }], +}); +``` + +### Bad + +```javascript +const orderSchema = new Schema({ + user: { type: Schema.Types.ObjectId }, // 缺少 ref,命名不规范 + products: [{ type: String }], // 应使用 ObjectId 引用 +}); +``` + +## 必须写明字段的类型 `[Js.Model.FieldType]` + +- 字段定义必须使用对象形式,明确指定 `type` 属性 +- 禁止使用简写形式(如 `field: String`) +- 不允许使用 Object 等模糊类型 + +### Good + +```javascript +const userSchema = new Schema({ + // 用户名 + user_name: { type: String, required: true }, + // 年龄 + age: { type: Number, default: 0 }, + // 是否激活 + is_active: { type: Boolean, default: true }, + // 创建时间 + created_at: { type: Date, default: Date.now }, +}); +``` + +### Bad + +```javascript +const userSchema = new Schema({ + user_name: String, // 缺少类型对象包装 + age: Number, + is_active: Boolean, + created_at: Date, + ext: { type: Object, default: {} }, + ext2: {}, +}); +```