Mongoose के पास स्कीमा और मॉडल दोनों क्यों हैं?


92

दो प्रकार की वस्तुएं एक-दूसरे के इतनी पास लगती हैं कि दोनों निरर्थक महसूस करती हैं। स्कीमा और मॉडल दोनों होने की बात क्या है ?

जवाबों:


61

अक्सर इस तरह के प्रश्न का उत्तर देने का सबसे आसान तरीका एक उदाहरण के साथ है। इस मामले में, किसी ने पहले ही मेरे लिए यह कर दिया है :)

यहाँ एक नज़र रखना:

http://rawberg.com/blog/nodejs/mongoose-orm-nested-models/

संपादित करें: मूल पोस्ट (जैसा कि टिप्पणियों में उल्लेख किया गया है) अब मौजूद नहीं है, इसलिए मैं इसे नीचे प्रस्तुत कर रहा हूं। क्या यह कभी वापस लौटना चाहिए, या यदि यह अभी स्थानांतरित हुआ है, तो कृपया मुझे बताएं।

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

मूल पोस्ट:

आइए एक मॉडल के अंदर एक स्कीमा को एम्बेड करने के सरल उदाहरण के साथ शुरू करें।

var TaskSchema = new Schema({
    name: String,
    priority: Number
});

TaskSchema.virtual('nameandpriority')
    .get( function () {
        return this.name + '(' + this.priority + ')';
    });

TaskSchema.method('isHighPriority', function() {
    if(this.priority === 1) {
        return true;
    } else {
        return false;
    }
}); 

var ListSchema = new Schema({
    name: String,
    tasks: [TaskSchema]
});

mongoose.model('List', ListSchema);

var List = mongoose.model('List');

var sampleList = new List({name:'Sample List'});

एक TaskSchemaबुनियादी जानकारी के साथ मैंने एक नई वस्तु बनाई जो एक कार्य हो सकती है। एक Mongoose आभासी विशेषता टास्क के नाम और प्राथमिकता को आसानी से संयोजित करने के लिए सेटअप है। मैंने यहां केवल एक गेट्टर निर्दिष्ट किया है, लेकिन वर्चुअल सेटर भी समर्थित हैं।

मैंने यह निर्धारित करने के लिए एक सरल कार्य विधि को भी परिभाषित isHighPriorityकिया कि इस सेटअप के साथ तरीके कैसे काम करते हैं।

में ListSchemaपरिभाषा आप कैसे कार्य कुंजी की एक सरणी धारण करने के लिए कॉन्फ़िगर किया गया है पर ध्यान देंगे TaskSchemaवस्तुओं। कार्य कुंजी एक उदाहरण बन जाएगी, DocumentArrayजो एम्बेडेड मैंगो दस्तावेजों से निपटने के लिए विशेष तरीके प्रदान करती है।

अभी के लिए मैंने केवल ListSchemaवस्तु को mongoose.model में पास किया और टास्कस्केमा को छोड़ दिया। तकनीकी रूप से इसे TaskSchemaऔपचारिक मॉडल में बदलना आवश्यक नहीं है क्योंकि हम इसे अपने संग्रह में सहेज नहीं रहे हैं। बाद में मैं आपको दिखाता हूँ कि यदि आप कुछ भी करते हैं तो यह कैसे नुकसान पहुँचाता है और यह आपके सभी मॉडलों को उसी तरह व्यवस्थित करने में मदद कर सकता है, खासकर जब वे कई फाइलों को फैलाना शुरू करते हैं।

साथ Listमॉडल सेटअप के यह करने के लिए एक जोड़े को कार्य जोड़ने और उन्हें बचाने मोंगो के लिए करते हैं।

var List = mongoose.model('List');
var sampleList = new List({name:'Sample List'});

sampleList.tasks.push(
    {name:'task one', priority:1}, 
    {name:'task two', priority:5}
);

sampleList.save(function(err) {
    if (err) {
        console.log('error adding new list');
        console.log(err);
    } else {
        console.log('new list successfully saved'); 
    }
});

हमारे Listमॉडल के उदाहरण पर कार्य विशेषता simpleListएक नियमित जावास्क्रिप्ट सरणी की तरह काम करती है और हम पुश का उपयोग करके इसमें नए कार्य जोड़ सकते हैं। ध्यान देने योग्य बात यह है कि कार्यों को नियमित जावास्क्रिप्ट वस्तुओं के रूप में जोड़ा जाता है। यह एक सूक्ष्म अंतर है जो तुरंत सहज नहीं हो सकता है।

आप मानगो शेल से सत्यापित कर सकते हैं कि नई सूची और कार्यों को मोंगो में सहेजा गया था।

db.lists.find()
{ "tasks" : [
    {
        "_id" : ObjectId("4dd1cbeed77909f507000002"),
        "priority" : 1,
        "name" : "task one"
    },
    {
        "_id" : ObjectId("4dd1cbeed77909f507000003"),
        "priority" : 5,
        "name" : "task two"
    }
], "_id" : ObjectId("4dd1cbeed77909f507000001"), "name" : "Sample List" }

अब हम इसके कार्यों के माध्यम ObjectIdसे खींचने Sample Listऔर पुनरावृति करने के लिए उपयोग कर सकते हैं ।

List.findById('4dd1cbeed77909f507000001', function(err, list) {
    console.log(list.name + ' retrieved');
    list.tasks.forEach(function(task, index, array) {
        console.log(task.name);
        console.log(task.nameandpriority);
        console.log(task.isHighPriority());
    });
});

यदि आप उस अंतिम बिट कोड को चलाते हैं, तो आपको यह कहते हुए एक त्रुटि मिलेगी कि एम्बेडेड दस्तावेज़ में कोई विधि नहीं है isHighPriority। Mongoose के वर्तमान संस्करण में आप सीधे एम्बेडेड स्कीमा पर तरीकों का उपयोग नहीं कर सकते। इसे ठीक करने के लिए एक खुला टिकट है और Mongoose Google समूह को प्रश्न प्रस्तुत करने के बाद, manimal45 ने अब उपयोग करने के लिए एक उपयोगी कार्य-आसन पोस्ट किया।

List.findById('4dd1cbeed77909f507000001', function(err, list) {
    console.log(list.name + ' retrieved');
    list.tasks.forEach(function(task, index, array) {
        console.log(task.name);
        console.log(task.nameandpriority);
        console.log(task._schema.methods.isHighPriority.apply(task));
    });
});

यदि आप उस कोड को चलाते हैं, तो आपको कमांड लाइन पर निम्न आउटपुट देखना चाहिए।

Sample List retrieved
task one
task one (1)
true
task two
task two (5)
false

मन में उस काम के साथ चलो TaskSchemaएक Mongoose मॉडल में बदल जाते हैं ।

mongoose.model('Task', TaskSchema);

var Task = mongoose.model('Task');

var ListSchema = new Schema({
    name: String,
    tasks: [Task.schema]
});

mongoose.model('List', ListSchema);

var List = mongoose.model('List');

TaskSchemaपरिभाषा से पहले तो मैं यह बाहर छोड़ दिया के समान है। एक बार इसका मॉडल बन जाने के बाद भी हम डॉट नोटेशन का उपयोग करके अंतर्निहित स्कीमा ऑब्जेक्ट तक पहुँच सकते हैं।

आइए एक नई सूची बनाएं और इसके भीतर दो टास्क मॉडल इंस्टेंस एम्बेड करें।

var demoList = new List({name:'Demo List'});

var taskThree = new Task({name:'task three', priority:10});
var taskFour = new Task({name:'task four', priority:11});

demoList.tasks.push(taskThree.toObject(), taskFour.toObject());

demoList.save(function(err) {
    if (err) {
        console.log('error adding new list');
        console.log(err);
    } else {
        console.log('new list successfully saved'); 
    }
});

जैसा कि हम टास्क मॉडल के उदाहरणों को सूची में एम्बेड कर रहे हैं, हम toObjectउनके डेटा को सादे जावास्क्रिप्ट ऑब्जेक्ट्स में परिवर्तित करने के लिए कह रहे हैं जो कि List.tasks DocumentArrayउम्मीद कर रहा है। जब आप मॉडल इंस्टेंस को सहेजते हैं तो इस तरह आपके एम्बेडेड दस्तावेज़ शामिल होंगे ObjectIds

पूरा कोड उदाहरण एक जिस्ट के रूप में उपलब्ध है । उम्मीद है कि ये काम-काज चिकनी चीजों की मदद करेंगे क्योंकि मानगो का विकास जारी है। मैं अभी भी Mongoose और MongoDB के लिए बहुत नया हूँ इसलिए कृपया टिप्पणी में बेहतर समाधान और सुझाव साझा करने के लिए स्वतंत्र महसूस करें। हैप्पी डाटा मॉडलिंग!


3
यह आमतौर पर एसओ में तैनात सवालों के जवाब के रूप में नंगे लिंक जमा नहीं करने की सिफारिश की जाती है क्योंकि लिंक काम करना बंद कर सकता है (जैसा कि इस मामले में है)। आपके द्वारा लिंक किए गए लेखों के संबंधित अनुभागों को कम से कम कॉपी / पास्ट और कोट करें।
बेहरंग सईदज़ादेह

1
किया - यह अभी भी Google कैश में था, इसलिए अपेक्षाकृत सरल था
एडम कॉमरफोर्ड

1
रिकॉर्ड के लिए, एम्बेडेड दस्तावेज़ विधि मुद्दा तय किया गया है: github.com/LearnBoost/mongoose/issues/249#ref-commit-e18077a
डकोटा

5
मैं किसी की परेड पर बारिश की कोशिश नहीं कर रहा हूं, लेकिन यह जवाब एक ट्यूटोरियल की तरह अधिक पढ़ा गया है: कैसे, लेकिन क्यों नहीं का जवाब देना। वोट कम होने के बावजूद, मुझे निम्नलिखित उत्तर बहुत अधिक मददगार लगे: stackoverflow.com/a/22950402/26331
अहीदन

2
मैंने उस उत्तर को देखा है (और इसे उखाड़ा है), यह एक उत्तर दिया गया था और उससे पहले 2 साल से अधिक समय के लिए स्वीकार किया गया था। मुझे खुशी है कि पाया जाने वाला एक बेहतर उत्तर है, किसी की परेड पर कोई बारिश नहीं हो रही है और फरवरी 2015 से आप इस सवाल के जवाब में जिस उत्तर का उल्लेख कर रहे हैं, उसके लिए एक लिंक दिया गया है, इसलिए मुझे इसे स्वयं लिंक करने की आवश्यकता महसूस नहीं हुई।
एडम कोमफोर्ड

54

स्कीमा एक ऐसी वस्तु है जो किसी भी दस्तावेज़ की संरचना को परिभाषित करती है जिसे आपके MongoDB संग्रह में संग्रहीत किया जाएगा; यह आपको अपने सभी डेटा आइटमों के प्रकार और सत्यापनकर्ताओं को परिभाषित करने में सक्षम बनाता है।

मॉडल एक ऐसी वस्तु है जो आपको एक नामित संग्रह तक आसान पहुंच प्रदान करती है, जिससे आप संग्रह को क्वेरी कर सकते हैं और स्कीमा का उपयोग करके उस संग्रह में सहेजे गए किसी भी दस्तावेज़ को मान्य कर सकते हैं। यह एक स्कीमा, एक कनेक्शन और एक संग्रह नाम के संयोजन से बनाया गया है।

मूल रूप से वैलेरी कारपोव, मोंगोडीबी ब्लॉग द्वारा प्रकाशित


5

मुझे नहीं लगता कि स्वीकृत उत्तर वास्तव में उस प्रश्न का उत्तर देता है जिसे प्रस्तुत किया गया था। उत्तर यह नहीं बताता है कि मोंगोस ने स्कीमा और मॉडल चर दोनों प्रदान करने के लिए एक डेवलपर की आवश्यकता क्यों तय की है। एक रूपरेखा का एक उदाहरण जहां उन्होंने डेवलपर की आवश्यकता को समाप्त कर दिया हैडेटा स्कीमा को परिभाषित करने के लिए django है - एक डेवलपर मॉडल मॉडल फ़ाइल में अपने मॉडल को लिखता है, और स्कीमा को प्रबंधित करने के लिए इसे फ्रेमवर्क पर छोड़ देता है। पहला कारण जो दिमाग में आता है कि वे ऐसा क्यों करते हैं, django के साथ मेरे अनुभव को देखते हुए, आसानी से उपयोग किया जाता है। शायद अधिक महत्वपूर्ण बात यह है कि DRY (खुद को दोहराएं नहीं) सिद्धांत - आपको मॉडल बदलने पर स्कीमा को अपडेट करने के लिए याद रखने की ज़रूरत नहीं है - django यह आपके लिए क्या करेगा! रेल आपके लिए डेटा के स्कीमा का प्रबंधन भी करती है - एक डेवलपर सीधे स्कीमा को संपादित नहीं करता है, लेकिन स्कीमा में हेरफेर करने वाले माइग्रेशन को परिभाषित करके इसे बदल देता है।

एक कारण मैं समझ सकता हूं कि मानगो स्कीमा को अलग करेगा और मॉडल ऐसे उदाहरण हैं जहां आप दो स्कीमाओं से एक मॉडल बनाना चाहते हैं। इस तरह का परिदृश्य प्रबंधन की तुलना में अधिक जटिलता का परिचय दे सकता है - यदि आपके पास दो स्कीमा हैं जो एक मॉडल द्वारा प्रबंधित हैं, तो वे एक स्कीमा क्यों नहीं हैं?

शायद मूल प्रश्न पारंपरिक संबंधपरक डेटाबेस प्रणाली का एक अवशेष है। दुनिया में NoSQL / Mongo दुनिया, शायद स्कीमा MySQL / PostgreSQL की तुलना में थोड़ी अधिक लचीली है, और इस प्रकार स्कीमा को बदलना अधिक सामान्य अभ्यास है।


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

0

समझने के लिए क्यों? आपको यह समझना होगा कि वास्तव में Mongoose क्या है?

अच्छी तरह से, मोंगोज़ मोंगोबीडीबी और नोड जेएस के लिए ऑब्जेक्ट डेटा मॉडलिंग लाइब्रेरी है, जो उच्च स्तर की अमूर्तता प्रदान करता है। तो यह एक्सप्रेस और नोड के बीच संबंध की तरह एक सा है, इसलिए एक्सप्रेस नियमित नोड पर अमूर्त की एक परत है, जबकि Mongoose नियमित MongoDB ड्राइवर पर अमूर्त की एक परत है।

एक ऑब्जेक्ट डेटा मॉडलिंग लाइब्रेरी हमारे लिए जावास्क्रिप्ट कोड लिखने का एक तरीका है जो तब एक डेटाबेस के साथ बातचीत करेगा। इसलिए हम अपने डेटाबेस तक पहुँचने के लिए बस एक नियमित MongoDB ड्राइवर का उपयोग कर सकते हैं, यह ठीक काम करेगा।

लेकिन इसके बजाय हम Mongoose का उपयोग करते हैं क्योंकि यह हमें बॉक्स से बहुत अधिक कार्यक्षमता प्रदान करता है, जिससे हमारे अनुप्रयोगों के तेज और सरल विकास की अनुमति मिलती है।

तो, कुछ सुविधाएँ Mongoose हमें हमारे डेटा और संबंध, आसान डेटा सत्यापन, एक साधारण क्वेरी API, मिडलवेयर और बहुत कुछ मॉडल करने के लिए स्कीमा देती हैं।

Mongoose में, एक स्कीमा वह है जहां हम अपना डेटा मॉडल करते हैं, जहां हम डेटा की संरचना, डिफ़ॉल्ट मान और सत्यापन का वर्णन करते हैं, फिर हम उस स्कीमा को लेते हैं और उसमें से एक मॉडल बनाते हैं, एक मॉडल मूल रूप से स्कीमा के चारों ओर एक आवरण होता है। जो हमें वास्तव में दस्तावेज़ बनाने, हटाने, अद्यतन करने और पढ़ने के लिए डेटाबेस के साथ इंटरफ़ेस करने की अनुमति देता है।

यहां छवि विवरण दर्ज करें

आइए एक स्कीमा से एक मॉडल बनाएं।

const tourSchema = new mongoose.Schema({
  name: {
    type: String,
    required: [true, 'A tour must have a name'],
    unique: true,
  },
  rating: {
    type: Number,
    default: 4.5,
  },
  price: {
    type: Number,
    required: [true, 'A tour must have a price'],
  },
});
//tour model
const Tour = mongoose.model('Tour', tourSchema);

एक मॉडल के नाम के पहले अक्षर के अनुसार, पूंजीकृत होना चाहिए।

आइए अपने मॉडल का उदाहरण बनाएं जिसे हमने मोंगो और स्कीमा का उपयोग करके बनाया है। इसके अलावा, हमारे डेटाबेस के साथ बातचीत।

const testTour = new Tour({ // instance of our model
  name: 'The Forest Hiker',
  rating: 4.7,
  price: 497,
});
 // saving testTour document into database
testTour
  .save()
  .then((doc) => {
    console.log(doc);
  })
  .catch((err) => {
    console.log(err);
  });

तो दोनों schama और modle mongoose होने से हमारा जीवन आसान हो जाता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.