एक नोड ऐप को व्यवस्थित कैसे करें जो सीक्वल का उपयोग करता है?


125

मैं एक उदाहरण नोडज एप्लिकेशन की तलाश कर रहा हूं जो सीक्वेलिज्म ओआरएम का उपयोग करता है।

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

मैं मुख्य रूप से इस बात में दिलचस्पी रखता हूं कि मॉडल को कैसे परिभाषित किया जाता है और ऐप के माध्यम से उपयोग किया जाता है। मैं कुछ मान्यता देना चाहूंगा कि मैं जो कुछ भी कर रहा हूं वह चीजों को करने का "अच्छा" तरीका है।


2
मैंने एक उदाहरण जोड़ा जो किसी को github.com/shaishab/fterelize-express-example
Shaishab Roy

: मैं के बारे में हमारे समाधान एक लेख लिखा है medium.com/@ismayilkhayredinov/...
hypeJunction

जवाबों:


125

लघुकथा

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

तो कदम हैं:

  • मॉडल के बारे में डेटा के साथ कई मॉडल फाइलें रखें, जैसे फ़ील्ड, रिश्ते और विकल्प।
  • एक सिंगलटन मॉड्यूल है जो उन सभी फाइलों को लोड करता है और सभी मॉडल कक्षाओं और संबंधों को सेटअप करता है।
  • App.js फ़ाइल में अपना सिंगलटन मॉड्यूल सेट करें।
  • सिंगलटन मॉड्यूल से मॉडल कक्षाएं प्राप्त करें अपने मॉडल फ़ाइलों पर उपयोग करें require, इसके बजाय सिंगलटन से मॉडल लोड करें।

लम्बी कहानी

इस स्रोत कोड के साथ इस समाधान का अधिक विस्तृत विवरण इस प्रकार है:

http://jeydotc.github.io/blog/2012/10/30/EXPRESS-WITH-SEQUELIZE.html

संपादित करें: यह एक बहुत पुराना उत्तर है! (जानकारी के लिए नीचे पढ़ें)

यह कई मायनों में पुराना और सीमित है!

  • सबसे पहले , जैसा कि @jinglesthula ने टिप्पणियों में उल्लेख किया है (और मैंने इसे भी अनुभव किया है) - उन फ़ाइलों की आवश्यकता के साथ समस्याएं हैं। क्योंकि यह requireउसी तरह से काम नहीं करता है readdirSync!

  • दूसरा - आप संबंधों में बहुत सीमित हैं - कोड उन संघों को विकल्प प्रदान नहीं करता है ताकि आप बनाने में असमर्थ होंbelongsToMany क्योंकि इसे throughसंपत्ति की आवश्यकता है। आप सबसे बुनियादी गधे बना सकते हैं।

  • तीसरा - आप मॉडल संबंधों में बहुत सीमित हैं! यदि आप कोड को बारीकी से पढ़ते हैं, तो आप देखेंगे कि संबंध एक ऐरे के बजाय एक ऑब्जेक्ट है , इसलिए यदि आप एक ही प्रकार के एक से अधिक संघ बनाना चाहते हैं (जैसे दो बार होना ) - आप नहीं कर सकते हैं!belongsTo

  • चौथा - आपको उस सिंगलटन चीज़ की ज़रूरत नहीं है। नोडज में हर मॉड्यूल अपने आप से सिंगलटन है, इसलिए यह सब बनाता है बिना किसी कारण के बहुत जटिल है।

आपको फ़ार्म का जवाब देखना चाहिए! (लेख का लिंक टूट गया है, लेकिन मैं इसे सीक्वल से इस आधिकारिक नमूने के साथ ठीक करूंगा: https://github.com/fterelize/express-example/blob/master/models/index.js - आप ब्राउज़ कर सकते हैं पूरे प्रोजेक्ट का अंदाजा लगा सकते हैं कि क्या चल रहा है)।

पी एस मैं इस पोस्ट को संपादित कर रहा हूं क्योंकि यह इतना उत्कीर्ण है कि लोग कोई नया उत्तर भी नहीं देखेंगे (जैसा मैंने किया)।

संपादित करें: लिंक को उसी पोस्ट की कॉपी में बदल दिया गया है, लेकिन एक Github पेज में


इसके अलावा, मैं इस धारणा के तहत था कि requireनोड में सभी डी मॉड्यूल एक अर्थ सिंगलटन में थे, क्योंकि उनमें कोड को एक बार निष्पादित किया गया था और फिर कैश किया गया था, ताकि अगली बार जब आपको उनकी आवश्यकता हो तो आपको एक कैश्ड ऑब्जेक्ट संदर्भ मिल रहा है। क्या यह पूरी तस्वीर नहीं है?
14

1
@mkoryak, आप सही हैं - नोड में सभी सामान्य मॉड्यूल प्रभावी रूप से एकल हैं, क्योंकि पहले निष्पादन के बाद लौटाया गया मान कैश किया जाता है। nodejs.org/api/modules.html#modules_caching
केसी फ्लिन

2
इसलिए, उदाहरण को सिंगलटन ट्रिकी पार्ट को हटाकर सरल बनाया जा सकता है और सिर्फ मॉड्यूल.टेक्स्पोर्ट्स = नया ऑरमक्लास () लगाया जा सकता है। मैं इसे
आज़माऊँगा

2
बस अगर किसी को मेरे पास सिरदर्द था, तो मैं आपको बचाऊंगा। मेरे पास जीथब लेख में सूचीबद्ध कोड के साथ मुद्दे थे जो रास्तों के आसपास केंद्रित थे। मुझे एक जोड़ना था। आवश्यकता के लिए (इस तरह: var ऑब्जेक्ट = आवश्यकता ('। + मॉडलपाठ + "/" + नाम);) और भी एक नाम डाल दिया अगर name.indexOf (' DS_Store ')> -1 init फ़ंक्शन में forEach (याय OSX)। उम्मीद है की वो मदद करदे।
jinglesthula

जैसा कि @jinglesthula ने उल्लेख किया है - निर्देशिका को हटाने वाली फ़ाइलों को लोड करने के लिए नमूने में कुछ परिवर्तन / कीड़े हैं (विशेषकर यदि यह कहीं न कहीं नेस्टेड है)। मैं संबंधों में विकल्पों को पारित करने की क्षमता भी जोड़ूंगा, क्योंकि वे बहुत महत्वपूर्ण हैं (जैसे कि विदेशी कुंजी का नाम, यदि यह अशक्त होने की अनुमति है, आदि)
एंड्री पोपोव

96

SequelizeJS का एक लेख है अपनी वेबसाइट पर जो इस समस्या को हल करता है।

लिंक टूट गया है, लेकिन आप यहां काम कर रहे नमूना परियोजना को पा सकते हैं और इसे ब्राउज़ कर सकते हैं। ऊपर संपादित उत्तर देखें कि यह एक बेहतर समाधान क्यों है।

लेख से निकालें:

  • मॉडल / index.js

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

          var fs        = require('fs')
            , path      = require('path')
            , Sequelize = require('sequelize')
            , lodash    = require('lodash')
            , sequelize = new Sequelize('sequelize_test', 'root', null)
            , db        = {} 
    
          fs.readdirSync(__dirname)
            .filter(function(file) {
              return (file.indexOf('.') !== 0) && (file !== 'index.js')
            })
            .forEach(function(file) {
              var model = sequelize.import(path.join(__dirname, file))
              db[model.name] = model
            })
    
          Object.keys(db).forEach(function(modelName) {
            if (db[modelName].options.hasOwnProperty('associate')) {
              db[modelName].options.associate(db)
            }
          })
    
          module.exports = lodash.extend({
            sequelize: sequelize,
            Sequelize: Sequelize
          }, db)

12
यह वह तरीका है जो Sequelize करने की सलाह देता है। मैं इसे सही उत्तर के रूप में स्वीकार करूंगा।
jpotts18

3
यह अच्छा है, लेकिन आप किसी अन्य मॉडल की इंस्टेंस विधियों से मॉडल का उपयोग नहीं कर सकते हैं, या शायद मैंने कुछ याद किया है।
mlkmt

1
पेज किसी भी अधिक मौजूद नहीं है
माइक Cheel

1
यहाँ काम कर रहा लिंक है: अगली
chrisg86

3
@mlkmt आप कर सकते हैं! चूंकि आपके पास sequelizeअपनी मॉडल फ़ाइल में चर तक पहुंच है , इसलिए आप अपने अन्य मॉडल के साथ पहुंच सकते हैं sequelize.models.modelName
गिलहर्मे सेहान

29

मैंने इस मुद्दे से निपटने में लोगों की मदद करने के लिए एक पैकेज सिक्वल-कनेक्ट बनाया है। यह Sequelize सुझाव सम्मेलन यहां इस प्रकार है: http://sequelize.readthedocs.org/en/1.7.0/articles/express/

इसके अतिरिक्त यह अपने इंटरफ़ेस के संदर्भ में Mongoose की तरह थोड़ा अधिक कार्य करता है। यह आपको उन स्थानों का एक सेट निर्दिष्ट करने की अनुमति देता है जहां आपके मॉडल स्थित हैं और आपको अपनी मॉडल फ़ाइलों से मिलान करने के लिए एक कस्टम मिलान फ़ंक्शन को परिभाषित करने की अनुमति देता है।

उपयोग मूल रूप से इस तरह है:

var orm = require('sequelize-connect');

orm.discover = ["/my/model/path/1", "/path/to/models/2"];      // 1 to n paths can be specified here
orm.connect(db, user, passwd, options);                        // initialize the sequelize connection and models

तब आप मॉडल का उपयोग कर सकते हैं और सीक्वेल कर सकते हैं:

var orm       = require('sequelize-connect');
var sequelize = orm.sequelize;
var Sequelize = orm.Sequelize;
var models    = orm.models;
var User      = models.User;

उम्मीद है कि यह किसी को बाहर करने में मदद करता है।


3
एक लेख से जोड़ने में थोड़ी मदद मिलती है। कुछ डॉक्स उद्धृत करना बेहतर है। एक कोड स्निपेट दिखाना बहुत अच्छा है .... लेकिन वास्तव में एक पुस्तकालय का निर्माण करना जो समस्या को हल करता है और इसे एनपीएम पर डालना शानदार है और अधिक प्यार करता है! +1 और आपकी परियोजना को तारांकित करेगा।
स्टिजन डे विट

9

मैंने Express.js ऐप में Sequelize का उपयोग करना शुरू कर दिया। जल्द ही आपके द्वारा बताए गए प्रकृति के मुद्दों में पर्याप्त भाग गया। शायद मैं सीक्वेलाइज को काफी समझ नहीं पाया था, लेकिन मुझे सिर्फ एक टेबल से चयन करने से ज्यादा चीजें करना वास्तव में सुविधाजनक नहीं था। और जहां आमतौर पर आप दो या अधिक तालिकाओं, या शुद्ध SQL में एक संघ से चयन का उपयोग करते हैं, आपको अलग-अलग क्वेरीज़ चलाना होगा, और नोड के async प्रकृति के साथ यह सिर्फ जटिलता जोड़ा गया है।

इसलिए मैं Sequelize का उपयोग करने से दूर चला गया। इसके अलावा मैं मॉडल में DB से किसी भी डेटा का उपयोग करने से स्विच कर रहा हूं। मेरी राय में डेटा प्राप्त करना पूरी तरह से अमूर्त करना बेहतर है। और कारण हैं - कल्पना करें कि आप MySQL का उपयोग नहीं करते हैं (मेरे मामले में, मैं MySQL और MongoDB पक्ष का उपयोग करता हूं), लेकिन आप किसी भी डेटा प्रदाता और किसी भी परिवहन विधि से अपना डेटा प्राप्त कर सकते हैं, जैसे SQL, no-SQL, फाइलसिस्टम, बाहरी एपीआई, एफ़टीपी, एसएसएच आदि। यदि आपने मॉडल में यह सब करने की कोशिश की है, तो आप अंततः कोड को समझने के लिए जटिल और कठिन बना देंगे, जो अपग्रेड और डीबग करना कठिन होगा।

अब क्या आप क्या करना चाहते मॉडल एक परत होती है जो जानता है कि कहाँ और कैसे इसे पाने के लिए से डेटा प्राप्त करने के लिए है, लेकिन अपने मॉडल केवल API तरीकों का उपयोग, जैसे fetch, save,delete आदि और यह परत के अंदर आप विशिष्ट डेटा प्रदाताओं के लिए विशिष्ट कार्यान्वयन है। उदाहरण के लिए, आप एक PHP मशीन से या फेसबुक एपीआई से या अमेज़ॅन एडब्ल्यूएस से या दूरस्थ एचटीएमएल दस्तावेज़ से कुछ डेटा का अनुरोध कर सकते हैं।

PS कुछ इन विचारों को Cloud9 द्वारा आर्किटेक्ट से उधार लिया गया था : http://events.yandex.ru/talks/300/


ये वैध अंक हैं, लेकिन मैं नहीं बल्कि reimplementing से बच जाएंगे fetch, save, deleteआदि के बाहर Sequelizeयह देखते हुए कि ढांचा पहले से ही साधन प्रदान करता है। यह एक अच्छा है, लेकिन एक अलग लेयरिंग परत के लिए कम सुविधाजनक है। एक ही समय में, आप शायद Sequelize के चारों ओर एक भ्रूण अमूर्त परत जोड़ सकते हैं, लेकिन फिर तर्कपूर्ण जीत के लिए समाधान अधिक जटिल है।
ज़ोरयार

यह ट्यूटोरियल बहुत हेल्पफूएल
लुकास डो अमरल

@ mvbl-fst आपने अभी एक DAO परत का वर्णन किया है। मान लें कि आपके पास SQL ​​DB में कुछ उपयोगकर्ता हैं और फाइल सिस्टम पर अलग-अलग उपयोगकर्ता हैं। आपके पास दो डीएओ होना चाहिए जो उनमें से प्रत्येक को प्राप्त करने के लिए सार है, फिर एक व्यावसायिक परत जो उपयोगकर्ताओं को एक साथ समेटती है (शायद कुछ गुणों को लागू भी करती है) और उन्हें आपके मार्ग (प्रस्तुति परत) पर वापस भेजती है।
डीजेडेवार्क

5

मैंने इसे फार्म के रूप में स्थापित किया और प्रलेखन का वर्णन किया।

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

उन्हें सभी मॉडलों के लिए सुलभ बनाकर इसे हल किया।

var Config = require('../config/config');

 var fs = require('fs');
var path = require('path');
var Sequelize = require('sequelize');
var _ = require('lodash');
var sequelize;
var db = {};

var dbName, dbUsername, dbPassword, dbPort, dbHost;
// set above vars

var sequelize = new Sequelize(dbName, dbUsername, dbPassword, {
dialect: 'postgres', protocol: 'postgres', port: dbPort, logging: false, host: dbHost,
  define: {
    classMethods: {
        db: function () {
                    return db;
        },
        Sequelize: function () {
                    return Sequelize;
        }

    }
  }
});


fs.readdirSync(__dirname).filter(function(file) {
   return (file.indexOf('.') !== 0) && (file !== 'index.js');
}).forEach(function(file) {
  var model = sequelize.import(path.join(__dirname, file));
  db[model.name] = model;
});

Object.keys(db).forEach(function(modelName) {
  if ('associate' in db[modelName]) {
      db[modelName].associate(db);
  }
});

module.exports = _.extend({
  sequelize: sequelize,
  Sequelize: Sequelize
}, db);

और मॉडल फ़ाइल में

var classMethods = {
  createFromParams: function (userParams) {
    var user = this.build(userParams);

    return this.db().PromoCode.find({where: {name: user.promoCode}}).then(function (code) {
        user.credits += code.credits;
                return user.save();
    });
  }

};

module.exports = function(sequelize, DataTypes) {
  return sequelize.define("User", {
  userId: DataTypes.STRING,
}, {  tableName: 'users',
    classMethods: classMethods
 });
};

मैंने केवल क्लास के तरीकों के लिए ऐसा किया था, लेकिन आप उदाहरण के तरीकों के लिए भी यही काम कर सकते हैं।


उस प्रोटोटाइप classMethod के लिए +1 जो db लौटाता है। वास्तव में वह विचार जिसे मैं परिभाषित करने के लिए क्लासमैथोड्स को लोड करने में सक्षम होने के लिए देख रहा था, लेकिन एक क्लासमैथोड में किसी भी मॉडल को संदर्भित करने में सक्षम हो सकता है (यानी रिश्तों को शामिल करने के लिए)
बिटविट

2

मैं आधिकारिक गाइड का पालन कर रहा हूं: http://fterelizejs.com/heroku , जिसमें एक मॉडल फ़ोल्डर है, प्रत्येक मॉड्यूल को अलग-अलग फ़ाइलों में सेट करें, और उन्हें आयात करने और उनके बीच संबंध स्थापित करने के लिए एक इंडेक्स फ़ाइल है।


लिंक मान्य नहीं है
prisar

2

नमूना मॉडल अगली कड़ी

'use strict';
const getRole   = require('../helpers/getRole')
const library   = require('../helpers/library')
const Op        = require('sequelize').Op

module.exports = (sequelize, DataTypes) => {
  var User = sequelize.define('User', {
    AdminId: DataTypes.INTEGER,
    name: {
      type: DataTypes.STRING,
      validate: {
        notEmpty: {
          args: true,
          msg: 'Name must be filled !!'
        },
      }
    },
    email: {
      type: DataTypes.STRING,
      validate: {
        notEmpty: {
          args: true,
          msg: 'Email must be filled !!'
        },
        isUnique: function(value, next) {
          User.findAll({
            where:{
              email: value,
              id: { [Op.ne]: this.id, }
            }
          })
          .then(function(user) {
            if (user.length == 0) {
              next()
            } else {
              next('Email already used !!')
            }
          })
          .catch(function(err) {
            next(err)
          })
        }
      }
    },
    password: {
      type: DataTypes.STRING,
      validate: {
        notEmpty: {
          args: true,
          msg: 'Password must be filled !!'
        },
        len: {
          args: [6, 255],
          msg: 'Password at least 6 characters !!'
        }
      }
    },
    role: {
      type: DataTypes.INTEGER,
      validate: {
        customValidation: function(value, next) {
          if (value == '') {
            next('Please choose a role !!')
          } else {
            next()
          }
        }
      }
    },
    gender: {
      type: DataTypes.INTEGER,
      validate: {
        notEmpty: {
          args: true,
          msg: 'Gender must be filled !!'
        },
      }
    },
    handphone: {
      type: DataTypes.STRING,
      validate: {
        notEmpty: {
          args: true,
          msg: 'Mobile no. must be filled !!'
        },
      }
    },
    address: DataTypes.TEXT,
    photo: DataTypes.STRING,
    reset_token: DataTypes.STRING,
    reset_expired: DataTypes.DATE,
    status: DataTypes.INTEGER
  }, {
    hooks: {
      beforeCreate: (user, options) => {
        user.password = library.encrypt(user.password)
      },
      beforeUpdate: (user, options) => {
        user.password = library.encrypt(user.password)
      }
    }
  });

  User.prototype.check_password = function (userPassword, callback) {
    if (library.comparePassword(userPassword, this.password)) {
      callback(true)
    }else{
      callback(false)
    }
  }

  User.prototype.getRole = function() {
    return getRole(this.role)
  }

  User.associate = function(models) {
    User.hasMany(models.Request)
  }

  return User;
};



1

आप के साथ मॉडल अन्य फ़ाइलों से आयात कर सकते हैं sequelize.import http://sequelizejs.com/documentation#models-import

इस तरह आपके पास सीक्वल के लिए एक सिंगलटन मॉड्यूल हो सकता है, जो तब अन्य सभी मॉडलों को लोड करता है।

वास्तव में यह उत्तर user1778770`s उत्तर के समान है।


1
परिपत्र निर्भरता के साथ यह काम करता है? उदाहरण के लिए जब मॉडल A में FK से मॉडल B और मॉडल के लिए FK से मॉडल A
mkoryak

1

मैं एक उदाहरण नोडज एप्लिकेशन की तलाश कर रहा हूं जो सीक्वेलिज्म ओआरएम का उपयोग करता है।

आपको PEAN.JS बायलरप्लेट समाधान को देखने में रुचि हो सकती है।

PEAN.JS एक पूर्ण-स्टैक जावास्क्रिप्ट ओपन-सोर्स समाधान है, जो PostgreSQL, Node.js, Express और AngularJS आधारित अनुप्रयोगों के लिए एक ठोस प्रारंभिक बिंदु प्रदान करता है।

PEAN परियोजना MEAN.JS परियोजना का एक कांटा है (MEAN.IO या सामान्य MEAN स्टैक के साथ भ्रमित होने की नहीं )।

PEAN ने MongoDB और Mongoose ORM को PostgreSQL और Sequelize से बदल दिया। MEAN.JS परियोजना का एक प्राथमिक लाभ यह संगठन है जो एक स्टैक को प्रदान करता है जिसमें कई चलती टुकड़े होते हैं।


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