2016-02-17 9 views
11

क्या आप कुछ अलग-अलग स्कीमा विकल्पों के संदर्भ के साथ एक मोंगोस स्कीमा में एक सरणी बना सकते हैं?एकल स्कीमा सरणी में एकाधिक स्कीमा संदर्भ - मोंगोस

var scenarioSchema = Schema({ 
    _id  : Number, 
    name : String, 
    guns : [] 
}); 

var ak47 = Schema({ 
    _id  : Number 
    //Bunch of AK specific parameters 
}); 

var m16 = Schema({ 
    _id  : Number 
    //Bunch of M16 specific parameters 
}); 

मैं ak47 या M16 के एक समूह के साथ बंदूकों सरणी पॉप्युलेट कर सकते हैं:

सवाल थोड़ा स्पष्ट करने के लिए, मैं निम्नलिखित स्कीमा है कहते हैं? क्या मैं उसी बंदूक सरणी में दोनों डाल सकता हूं? या क्या इसे संपत्ति सरणी में एक जनसंख्या रेफरी की आवश्यकता है, इस तरह, जो इसे एक विशिष्ट प्रकार तक सीमित करता है?

guns: [{ type: Schema.Types.ObjectId, ref: 'm16' }] 

मैं मैं सिर्फ अलग बंदूक प्रकार के लिए अलग सरणियों हो सकता है, लेकिन है कि परियोजना के तराजू, जिनमें से अधिकांश लोड परिदृश्य के आधार पर खाली छोड़ दिया जाएगा क्योंकि स्कीमा में अतिरिक्त क्षेत्रों का एक पागल राशि पैदा करेगा।

var scenarioSchema = Schema({ 
    _id  : Number, 
    name : String, 
    ak47s : [{ type: Schema.Types.ObjectId, ref: 'ak47' }], 
    m16s: [{ type: Schema.Types.ObjectId, ref: 'm16' }] 
}); 

तो सवाल पर वापस, क्या मैं एक ही सरणी में एकाधिक स्कीमा संदर्भों को छू सकता हूं?

उत्तर

16

जो आप यहां देख रहे हैं वह mongoose .discriminator() विधि है। यह मूल रूप से आपको एक ही संग्रह में विभिन्न प्रकार की वस्तुओं को स्टोर करने की अनुमति देता है, लेकिन उन्हें प्रथम श्रेणी की वस्तुओं के रूप में दूर करने योग्य बनाता है।

ध्यान दें कि "समान संग्रह" सिद्धांत यहां महत्वपूर्ण है कि .populate() कार्य और संदर्भ मॉडल में संदर्भ की परिभाषा कैसे महत्वपूर्ण है। चूंकि आप वास्तव में संदर्भ के लिए केवल "एक" मॉडल को इंगित कर सकते हैं, लेकिन कुछ अन्य जादू है जो एक मॉडल को कई लोगों के रूप में प्रदर्शित कर सकता है।

उदाहरण लिस्टिंग:

var util = require('util'), 
    async = require('async'), 
    mongoose = require('mongoose'), 
    Schema = mongoose.Schema; 

mongoose.connect('mongodb://localhost/gunshow'); 

//mongoose.set("debug",true); 

var scenarioSchema = new Schema({ 
    "name": String, 
    "guns": [{ "type": Schema.Types.ObjectId, "ref": "Gun" }] 
}); 

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

    // Common Gun stuff 
    this.add({ 
    "createdAt": { "type": Date, "default": Date.now } 
    }); 
} 

util.inherits(BaseSchema, Schema); 

var gunSchema = new BaseSchema(); 

var ak47Schema = new BaseSchema({ 
    // Ak74 stuff 
}); 

ak47Schema.methods.shoot = function() { 
    return "Crack!Crack"; 
}; 

var m16Schema = new BaseSchema({ 
    // M16 Stuff 
}); 

m16Schema.methods.shoot = function() { 
    return "Blam!!" 
}; 


var Scenario = mongoose.model("Scenario", scenarioSchema); 

var Gun = mongoose.model("Gun", gunSchema); 
var Ak47 = Gun.discriminator("Ak47", ak47Schema); 
var M16 = Gun.discriminator("M16", m16Schema); 


async.series(
    [ 
    // Cleanup 
    function(callback) { 
     async.each([Scenario,Gun],function(model,callback) { 
     model.remove({},callback); 
     },callback); 
    }, 

    // Add some guns and add to scenario 
    function(callback) { 
     async.waterfall(
     [ 
      function(callback) { 
      async.map([Ak47,M16],function(gun,callback) { 
       gun.create({},callback); 
      },callback); 
      }, 
      function(guns,callback) { 
      Scenario.create({ 
       "name": "Test", 
       "guns": guns 
      },callback); 
      } 
     ], 
     callback 
    ); 
    }, 

    // Get populated scenario 
    function(callback) { 
     Scenario.findOne().populate("guns").exec(function(err,data) { 

     console.log("Populated:\n%s",JSON.stringify(data,undefined,2)); 

     // Shoot each gun for fun! 
     data.guns.forEach(function(gun) { 
      console.log("%s says %s",gun.__t,gun.shoot()); 
     }); 

     callback(err); 
     }); 
    }, 

    // Show the Guns collection 
    function(callback) { 
     Gun.find().exec(function(err,guns) { 
     console.log("Guns:\n%s", JSON.stringify(guns,undefined,2)); 
     callback(err); 
     }); 
    }, 

    // Show magic filtering 
    function(callback) { 
     Ak47.find().exec(function(err,ak47) { 
     console.log("Magic!:\n%s", JSON.stringify(ak47,undefined,2)); 
     callback(err); 
     }); 
    } 
    ], 
    function(err) { 
    if (err) throw err; 
    mongoose.disconnect(); 
    } 
); 

और उत्पादन

Populated: 
{ 
    "_id": "56c508069d16fab84ead921d", 
    "name": "Test", 
    "__v": 0, 
    "guns": [ 
    { 
     "_id": "56c508069d16fab84ead921b", 
     "__v": 0, 
     "__t": "Ak47", 
     "createdAt": "2016-02-17T23:53:42.853Z" 
    }, 
    { 
     "_id": "56c508069d16fab84ead921c", 
     "__v": 0, 
     "__t": "M16", 
     "createdAt": "2016-02-17T23:53:42.862Z" 
    } 
    ] 
} 
Ak47 says Crack!Crack 
M16 says Blam!! 
Guns: 
[ 
    { 
    "_id": "56c508069d16fab84ead921b", 
    "__v": 0, 
    "__t": "Ak47", 
    "createdAt": "2016-02-17T23:53:42.853Z" 
    }, 
    { 
    "_id": "56c508069d16fab84ead921c", 
    "__v": 0, 
    "__t": "M16", 
    "createdAt": "2016-02-17T23:53:42.862Z" 
    } 
] 
Magic!: 
[ 
    { 
    "_id": "56c508069d16fab84ead921b", 
    "__v": 0, 
    "__t": "Ak47", 
    "createdAt": "2016-02-17T23:53:42.853Z" 
    } 
] 

तुम भी mongoose.set("debug",true) लाइन सूची में कैसे नेवला वास्तव में कॉल निर्माण कर रही है को देखने के लिए uncomment कर सकते हैं।

तो यह दर्शाता है कि आप विभिन्न प्रथम श्रेणी वस्तुओं के लिए अलग-अलग स्कीमा लागू कर सकते हैं, और यहां तक ​​कि असली वस्तुओं की तरह उनके साथ जुड़े विभिन्न तरीकों के साथ भी। नेवला सभी संलग्न मॉडल के साथ एक "बंदूकों" संग्रह में इन भंडारण है, और यह सब "प्रकार" discriminator द्वारा refernced में शामिल होंगे:

var Gun = mongoose.model("Gun", gunSchema); 
var Ak47 = Gun.discriminator("Ak47", ak47Schema); 
var M16 = Gun.discriminator("M16", m16Schema); 

लेकिन यह भी प्रत्येक अलग "प्रकार" में उसके अपने मॉडल के साथ संदर्भित है एक विशेष तरीका तो आप देखते हैं कि जब मोंगोज़ ऑब्जेक्ट को स्टोर करता है और पढ़ता है, तो एक विशेष __t फ़ील्ड होता है जो बताता है कि कौन सा "मॉडल" लागू करना है, और इसलिए स्कीमा संलग्न है।

एक उदाहरण के रूप में हम .shoot() विधि को कॉल करते हैं, जिसे प्रत्येक मॉडल/स्कीमा के लिए अलग-अलग परिभाषित किया जाता है। और आप अभी भी प्रश्नों या अन्य परिचालनों के लिए मॉडल के रूप में प्रत्येक का उपयोग कर सकते हैं, क्योंकि Ak47 स्वचालित रूप से सभी क्वेरी/अपेट्स में __t मान लागू करेगा।

हालांकि स्टोरेज एक संग्रह में है, लेकिन यह कई संग्रह प्रतीत होता है, लेकिन उन्हें अन्य उपयोगी संचालन के लिए एक साथ रखने का लाभ भी है। इस प्रकार आप "पॉलिमॉर्फिज्म" की तरह आवेदन कर सकते हैं जिसे आप ढूंढ रहे हैं।

+0

वाह जो सुपर सूचनात्मक था! धन्यवाद!! – BrentShanahan

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