2013-08-19 16 views
15

वर्तमान में मैं दो लगभग समान स्कीमा है:नेवला: विस्तार स्कीमा

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, lastname या फोन की जरूरत नहीं है। हालांकि व्यवस्थापक इन गुणों को परिभाषित किया जाना चाहिए।

दुर्भाग्यवश उपरोक्त कोड बहुत शुष्क नहीं है, क्योंकि वे लगभग समान हैं। इसलिए मैं सोच रहा हूं कि userSchema के आधार पर बनाना संभव है या नहीं। उदा .:

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

जाहिर है कि यह सिर्फ छद्म कोड है। क्या ऐसा कुछ संभव है?

एक और बहुत ही समान सवाल यह है कि यदि किसी अन्य पर आधारित एक नई स्कीमा बनाना संभव है, और इसमें कुछ और गुण जोड़ें। उदाहरण के लिए:

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); 

यह है, जब से तुम एक ही वस्तु संशोधित कर रहे हैं। इसके अलावा, मैं इस प्रकार मेरी पसंदीदा तरीका पीछा कर रहा है प्लगइन्स और तरीकों आदि का विस्तार करने में सक्षम होना चाहते हैं:

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

धन्यवाद। दुर्भाग्य से ऐसा लगता है कि इन सभी समाधानों में कुछ जटिलता शामिल है। यहां तक ​​कि पहले एक ऐसे परिस्थिति में परिणाम जहां हमारे पास अब उपयोगकर्ता सेटिंग्स हैं, उपयोगकर्ता स्केमा और उपयोगकर्ता मॉडल। Use.inherits एक क्लीनर दृष्टिकोण होगा? अनुलेख मुझे लगता है कि आपके दूसरे उदाहरण में एक टाइपो है। यह 'var adminSchema = UserSchema() {..' – Tom

+0

[यह थ्रेड] होना चाहिए (https://groups.google.com/forum/#!topic/mongoose-orm/aeqGRRnpFvg) ऐसी विरासत पर चर्चा करता है। मुझे यह क्लीनर नहीं मिला है (यह उतना ही कोड है लेकिन उलझन में है) और कुछ लोग इसका गंदा मानते हैं। –

24

नेवला अब 3.8.1 discriminators के लिए समर्थन हासिल है। एक नमूना है, यहाँ से: 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

@ डिप्रोआर्ट यह थोड़ा पुराना है, लेकिन यदि आप इसे '15 में पढ़ रहे हैं, तो मोंगोस-स्कीमा-विस्तार का उपयोग न करें।बहुत सारे मुद्दे खोले गए हैं और प्लगइन को '13 से अपडेट नहीं किया गया है। यदि आप मुद्दों का अनुभव नहीं करना चाहते हैं तो mongoose "Discriminators" के लिए जाएं ... – romualdr

+1

अब यह सक्रिय रूप से बनाए रखा गया है, लेकिन भेदभाव करने वालों पर भरोसा करना एक अच्छा विचार हो सकता है –

2

इस चर्चा को जोड़ने के लिए, आप भी कस्टम आधार स्कीमा परिभाषा के साथ mongoose.Schema ओवरराइड कर सकते हैं। कोड संगतता के लिए, अगर कथन जोड़ें जो स्कीमा को new के बिना तुरंत चालू करने की अनुमति देता है। हालांकि यह सुविधाजनक हो सकता है, सार्वजनिक पैकेज में ऐसा करने से पहले दो बार सोचें।

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 प्रकाशित किया है। हालांकि मैंने कुछ परीक्षण किया है, यह अभी भी एक प्रयोगात्मक चरण में है। मुझे यह जानने में दिलचस्पी है कि क्या यह मेरे साथी एसओ उपयोगकर्ताओं के अनुप्रयोगों के लिए अच्छा काम करता है!

मॉड्यूल एक विरासत() सुविधा फ़ंक्शन प्रदान करता है जो एक माता-पिता मॉडल और एक बच्चे स्कीमा एक्सटेंशन के आधार पर एक बच्चे Mongoose.js मॉडल देता है। यह पैरेंट मॉडल विधियों को कॉल करने के लिए एक सुपर() विधि के साथ मॉडलों को भी बढ़ाता है। मैंने इस कार्यक्षमता को जोड़ा क्योंकि यह कुछ ऐसा है जिसे मैं अन्य एक्सटेंशन/विरासत पुस्तकालयों में याद करता हूं।

उत्तराधिकारी सुविधा फ़ंक्शन बस discriminator method का उपयोग करता है।

0

मुझे भेदभाव की आवश्यकता नहीं थी, क्योंकि मैं उप दस्तावेज़ स्कीमा का विस्तार करने की कोशिश कर रहा था जिसे किसी भी मूल दस्तावेज़ के हिस्से के रूप में संग्रहीत किया जाता है।

मेरा समाधान बेस स्कीमा की स्कीमा को "विस्तारित" विधि जोड़ना था, ताकि आप या तो आधार स्कीमा का उपयोग कर सकें या इसके आधार पर एक नई स्कीमा उत्पन्न कर सकें।

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

आप मूल स्कीमा # obj विस्तार कर सकते हैं:

स्थिरांक 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

इन सभी उत्तर या बल्कि बेकार में जटिल लग, विस्तार सहायक कार्यों के साथ स्कीमा या plugins/discriminators का उपयोग कर के लिए लागू तरीकों का विस्तार। मैंने निम्नलिखित समाधान का उपयोग किया है जो कि सरल, साफ और काम करने में आसान है। यह आधार स्कीमा के लिए एक खाका को परिभाषित करता है, और फिर वास्तविक स्कीमा का खाका से बन रहे हैं:

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; 

आप मूल स्कीमा के लिए खाका का उपयोग कर सकते है, और का उपयोग कर Object.assign आप एक ही ऑब्जेक्ट को संशोधित किए बिना, अन्य स्कीमा के लिए किसी भी तरह से ब्लूप्रिंट का विस्तार कर सकते हैं।

संबंधित मुद्दे