2013-08-19 9 views
15

は現在、私は2つのほとんど同じスキーマを持っている:マングース:拡張スキーマ

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}, 

}); 

そして

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}, 

}); 

彼らの唯一の違いは検証中です:ユーザーがFIRSTNAME、姓や電話は必要ありません。ただし、管理者はこれらのプロパティを定義する必要があります。

残念ながら、上記のコードはあまりDRYではありません。ほとんど同じです。したがって、userSchemaに基づいてadminSchemaを構築することが可能かどうかは疑問です。例:

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

明らかにそれは疑似コードです。このようなことは可能でしょうか?

もう1つの非常によく似た質問は、別のものに基づいて新しいスキーマを作成し、それにいくつかのプロパティを追加できるかどうかです。たとえば、

var adminSchema = mongoose.Schema(userSchema); 
    adminSchema.add(adminPower: Number); 
+0

そして、人々はそれをするhttps://github.com/briankircho/mongoose-schema-extendこれを参照してください。 – diproart

答えて

7

suggested using utils.inheritsにはスキーマを拡張する人がいます。あなたが同じオブジェクトを変更しているので、

var settings = { 
    one: Number 
}; 

new Schema(settings); 

settings.two = Number; 
new Schema(settings); 

それは、しかし少し醜いです:もう一つの簡単な方法は、単純に設定してオブジェクトを設定し、それからスキーマを作成し、そのようにすることです。また、私はこのように私の好ましい方法は、以下れるプラグインや方法などを拡張できるようにしたいと思います:あなたの2つ目の質問に答えるために起こる

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

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

    return schema; 
} 

var userSchema = UserSchema(); 
var adminSchema = UserSchema({ 
    anotherField: String 
}); 

そのはい、することができますadd()フィールド。したがって、上記の機能の修正版があなたの問題を解決するだろう、スキーマのいくつかのプロパティを変更する:

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; 
} 
+0

ありがとうございます。残念ながら、これらのソリューションはすべて複雑なものになっているようです。最初のものでさえ、userSettings、userSchema、およびuserModelを持つ状況になります。 util.inheritsはよりクリーンなアプローチですか? P.S.あなたの2番目の例では、タイプミスがあると思います。 'var adminSchema = UserSchema(){..' – Tom

+0

[このスレッド](https://groups.google.com/forum/#!topic/mongoose-orm/aeqGRRnpFvg)は、そのような継承を説明しています。私はそれが(より多くのコードが醜いだけでなく)掃除機を見つけることはありませんが、いくつかの人々はバギーだと言います。 –

24

マングース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); 
+1

そして、人々はそれをするhttps://github.com/briankircho/mongoose-schema-extendこれを参照してください。 – diproart

+11

@diproartこれは少し古いですが、15年にこれを読んでいるなら、mongoose-schema-extendを使わないでください。開かれた問題はたくさんあります。プラグインは'13年から更新されていません。あなたが問題を経験したくない場合は、モンゴーズの "Discriminators"に行ってください... – romualdr

+1

これは現在積極的に維持されていますが、とにかく弁別者に頼ることは良い考えです –

2

この議論に追加するには、あなたはまた、カスタムベーススキーマ定義でmongoose.Schemaを上書きすることができます。コードの互換性のために、newなしでスキーマをインスタンス化できるようにするifステートメントを追加します。これは便利なことですが、公開パッケージでこれを行う前に2度考えてください。

var Schema = mongoose.Schema; 

var BaseSyncSchema = function(obj, options) { 

    if (!(this instanceof BaseSyncSchema)) 
     return new BaseSyncSchema(obj, options); 

    Schema.apply(this, arguments); 

    this.methods.update = function() { 
     this.updated = new Date(); 
    }; 

    this.add({ 
     updated: Date 
    }); 
}; 
util.inherits(BaseSyncSchema, Schema); 

// Edit!!! 
// mongoose.Schema = BaseSyncSchema; <-- Does not work in mongoose 4 
// Do this instead: 
Object.defineProperty(mongoose, "Schema", { 
    value: BaseSyncSchema, 
    writable: false 
}); 
2

私はちょうどmongoose-super npm moduleを発行しました。私はいくつかのテストを行ったが、まだ実験段階にある。私はそれが私の仲間のSOユーザーのアプリケーションのためにうまく動作するかどうかを知ることに興味があります!

モジュールは、親モデルと子スキーマ拡張に基づいて子Mongoose.jsモデルを返すinherit()便利関数を提供します。また、親モデルのメソッドを呼び出すためにsuper()メソッドを使用してモデルを補強します。私はこの機能を追加しました。これは、他の拡張/継承ライブラリで見逃していたものです。

継承便宜関数は単にdiscriminator methodを使用します。

0

親ドキュメントの一部として格納されているサブドキュメントスキーマを拡張しようとしていたため、差別化は必要ありませんでした。

私の解決策は、基本スキーマであるスキーマに "extend"メソッドを追加することで、基本スキーマ自体を使用するか、それに基づいて新しいスキーマを生成することでした。

ES6コードは次のとおりです。

'use strict'; 

//Dependencies 
let Schema = require('mongoose').Schema; 

//Schema generator 
function extendFooSchema(fields, _id = false) { 

    //Extend default fields with given fields 
    fields = Object.assign({ 
    foo: String, 
    bar: String, 
    }, fields || {}); 

    //Create schema 
    let FooSchema = new Schema(fields, {_id}); 

    //Add methods/options and whatnot 
    FooSchema.methods.bar = function() { ... }; 

    //Return 
    return FooSchema; 
} 

//Create the base schema now 
let FooSchema = extendFooSchema(null, false); 

//Expose generator method 
FooSchema.extend = extendFooSchema; 

//Export schema 
module.exports = FooSchema; 

あなたは今、このスキーマを使用するか、または必要に応じてそれを「拡張」することができます。この場合、

let BazSchema = FooSchema.extend({baz: Number}); 

拡張は、ブランドの新しいスキーマ定義を作成します。

0

元のスキーマ#1 OBJ拡張することができる:

CONST AdminSchema =新しい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: '[email protected]', 
    passwordHash: 'bla-bla-bla', 
    firstname: 'John' 
}); 

john.save(); 

const admin = new AdminUser({ 
    email: '[email protected]', 
    passwordHash: 'bla-bla-bla', 
    firstname: 'Henry', 
    lastname: 'Hardcore', 
    // phone: '+555-5555-55' 
}); 

admin.save(); 
// Oops! Error 'phone' is required 

、同じアプローチを用いて、この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} 
}); 

チェックGitHubのレポhttps://github.com/doasync/mongoose-extend-schema

0

これらの答えのすべては、拡張ヘルパー関数で、むしろ不必要に複雑に見えるか、スキーマのやプラグイン/弁別を使用して適用される方法を拡張します。私は単純で、きれいで、扱いやすい次のソリューションを代わりに使用しました。これは、基本スキーマのための青写真を定義し、その後、実際のスキーマのは、青写真を使用して構築されています:

foo.blueprint.js

module.exports = { 
    schema: { 
    foo: String, 
    bar: Number, 
    }, 
    methods: { 
    fooBar() { 
     return 42; 
    }, 
    } 
}; 

foo.schema.js

const {schema, methods} = require('./foo.blueprint'); 
const {Schema} = require('mongoose'); 
const FooSchema = new Schema(foo); 
Object.assign(FooSchema.methods, methods); 
module.exports = FooSchema; 

バー。 schema.js

const {schema, methods} = require('./foo.blueprint'); 
const {Schema} = require('mongoose'); 
const BarSchema = new Schema(Object.assign({}, schema, { 
    bar: String, 
    baz: Boolean, 
})); 
Object.assign(BarSchema.methods, methods); 
module.exports = BarSchema; 

あなたがあるとして、元のスキーマのための青写真を使用し、を使用することができますでは、同じオブジェクトを変更せずに、他のスキーマのように任意の方法で青写真を拡張できます。

関連する問題