猫鼬:扩展模式

Tom*_*Tom 20 schema mongoose node.js

目前我有两个几乎相同的模式:

var userSchema = mongoose.Schema({

    email: {type: String, unique: true, required: true, validate: emailValidator},
    passwordHash: {type: String, required: true},

    firstname: {type: String, validate: firstnameValidator},
    lastname: {type: String, validate: lastnameValidator},
    phone: {type: String, validate: phoneValidator},

});
Run Code Online (Sandbox Code Playgroud)

var adminSchema = mongoose.Schema({

    email: {type: String, unique: true, required: true, validate: emailValidator},
    passwordHash: {type: String, required: true},

    firstname: {type: String, validate: firstnameValidator, required: true},
    lastname: {type: String, validate: lastnameValidator, required: true},
    phone: {type: String, validate: phoneValidator, required: true},

});
Run Code Online (Sandbox Code Playgroud)

他们唯一的区别在于验证:用户不需要名字,姓氏或电话.但是,管理员必须定义这些属性.

不幸的是,上面的代码不是很干,因为它们几乎相同.因此,我想知道是否有可能建立一个adminSchema基于userSchema.例如:

var adminSchema = mongoose.Schema(userSchema);
adminSchema.change('firstname', {required: true});
adminSchema.change('lastname', {required: true});
adminSchema.change('phone', {required: true});
Run Code Online (Sandbox Code Playgroud)

显然这只是伪代码.这样的事情可能吗?

另一个非常相似的问题是,是否可以基于另一个创建新模式,并为其添加更多属性.例如:

var adminSchema = mongoose.Schema(userSchema);
    adminSchema.add(adminPower: Number);
Run Code Online (Sandbox Code Playgroud)

reg*_*low 30

Mongoose 3.8.1现在支持歧视者.一个样本,来自这里:http://mongoosejs.com/docs/api.html#model_Model.discriminator

function BaseSchema() {
  Schema.apply(this, arguments);

  this.add({
    name: String,
    createdAt: Date
  });
}
util.inherits(BaseSchema, Schema);

var PersonSchema = new BaseSchema();
var BossSchema = new BaseSchema({ department: String });

var Person = mongoose.model('Person', PersonSchema);
var Boss = Person.discriminator('Boss', BossSchema);
Run Code Online (Sandbox Code Playgroud)

  • @diproart它有点旧,但是如果你在15年读这个,不要使用mongoose-schema-extend.自13年以来,打开了许多问题并且插件尚未更新.如果您不想遇到问题,请选择猫鼬"鉴别者"...... (13认同)

nak*_*iin 14

扩展猫鼬模式的最简单方法

import { model, Schema } from 'mongoose';

const ParentSchema = new Schema({
  fromParent: Boolean
});

const ChildSchema = new Schema({
  ...ParentSchema.obj,
  fromChild: Boolean // new properties come up here
});

export const Child = model('Child', ChildSchema);
Run Code Online (Sandbox Code Playgroud)


And*_*ren 10

有些人在其他地方建议使用utils.inherits来扩展模式.另一种简单的方法是简单地设置一个带有设置的对象并从中创建Schema,如下所示:

var settings = {
  one: Number
};

new Schema(settings);

settings.two = Number;
new Schema(settings);
Run Code Online (Sandbox Code Playgroud)

虽然它有点难看,因为你正在修改同一个对象.此外,我希望能够扩展插件和方法等.因此,我首选的方法如下:

function UserSchema (add) {
  var schema = new Schema({
    someField: String
  });

  if(add) {
    schema.add(add);
  }

  return schema;
}

var userSchema = UserSchema();
var adminSchema = UserSchema({
  anotherField: String
});
Run Code Online (Sandbox Code Playgroud)

这恰好回答了你的第二个问题,是的,你可以add()填写.因此,要修改Schema的某些属性,上述函数的修改版本将解决您的问题:

function UserSchema (add, nameAndPhoneIsRequired) {
  var schema = new Schema({
    //...
    firstname: {type: String, validate: firstnameValidator, required: nameAndPhoneIsRequired},
    lastname: {type: String, validate: lastnameValidator, required: nameAndPhoneIsRequired},
    phone: {type: String, validate: phoneValidator, required: nameAndPhoneIsRequired},
  });

  if(add) {
    schema.add(add);
  }

  return schema;
}
Run Code Online (Sandbox Code Playgroud)


Def*_*Day 7

也许在猫鼬的更高版本中这变得更容易了。

const ToySchema = new Schema();
ToySchema.add({ name: 'string', color: 'string', price: 'number' });

const TurboManSchema = new Schema();
// You can also `add()` another schema and copy over all paths, virtuals,
// getters, setters, indexes, methods, and statics.
TurboManSchema.add(ToySchema).add({ year: Number });
Run Code Online (Sandbox Code Playgroud)

参考: https: //mongoosejs.com/docs/api/schema.html#schema_Schema-add

  • 这应该是 2023 年公认的答案,因为这也复制了方法、静态、虚拟等。 (3认同)

Do *_*ync 5

您可以扩展原始的Schema#obj

const AdminSchema = new mongoose.Schema({},Object.assign(UserSchema.obj,{...}))

例:

const mongoose = require('mongoose');

const UserSchema = new mongoose.Schema({
  email: {type: String, unique: true, required: true},
  passwordHash: {type: String, required: true},

  firstname: {type: String},
  lastname: {type: String},
  phone: {type: String}
});

// Extend function
const extend = (Schema, obj) => (
  new mongoose.Schema(
    Object.assign({}, Schema.obj, obj)
  )
);

// Usage:
const AdminUserSchema = extend(UserSchema, {
  firstname: {type: String, required: true},
  lastname: {type: String, required: true},
  phone: {type: String, required: true}
});

const User = mongoose.model('users', UserSchema);
const AdminUser = mongoose.model('admins', AdminUserSchema);

const john = new User({
  email: 'user@site.com',
  passwordHash: 'bla-bla-bla',
  firstname: 'John'
});

john.save();

const admin = new AdminUser({
  email: 'admin@site.com',
  passwordHash: 'bla-bla-bla',
  firstname: 'Henry',
  lastname: 'Hardcore',
  // phone: '+555-5555-55'
});

admin.save();
// Oops! Error 'phone' is required
Run Code Online (Sandbox Code Playgroud)

或使用相同的方法使用此npm模块:

const extendSchema = require('mongoose-extend-schema'); // not 'mongoose-schema-extend'

const UserSchema = new mongoose.Schema({
  firstname: {type: String},
  lastname: {type: String}
});

const ClientSchema = extendSchema(UserSchema, {
  phone: {type: String, required: true}
});
Run Code Online (Sandbox Code Playgroud)

检查github仓库https://github.com/doasync/mongoose-extend-schema