precursor Δημοσ. 17 Ιουλίου 2018 Μέλος Δημοσ. 17 Ιουλίου 2018 (επεξεργασμένο) Στις 13/7/2018 στις 11:18 ΠΜ, paparovic είπε β) Copy/paste από το πώς το στήνω εγώ και μετά σχόλια για το πώς θα το κάνεις εσύ: // `models/index.js` const Sequelize = require('sequelize'); const FS = require('fs'); const Path = require('path'); const config = require('../config'); const sequelize = new Sequelize( config.postgres.db, config.postgres.user, config.postgres.password, { host: config.postgres.host, dialect: 'postgres', logging: false, operatorsAliases: false, pool: { max: 5, idle: 30000, acquire: 60000, }, define: { charset: 'utf8', collate: 'utf8_general_ci', timestamps: true }, sync: { alter: true }, }, ); const db = {}; FS.readdirSync(__dirname) .filter(function (file) { return (file.indexOf(".") !== 0) && (file !== "index.js"); }) .forEach(function (file) { const 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); } }); db.sequelize = sequelize; db.Sequelize = Sequelize; module.exports = db; // `models/patata.js` module.exports = function (sequelize, DataTypes) { const Patata = sequelize.define("Patata", { type: DataTypes.STRING, isActive: DataTypes.BOOLEAN, }, { tableName: 'Patata', timestamps: true, paranoid: true, updatedAt: true, }); Patata.associate = function (models) { Test.belongsTo(models.Tsanta, {foreignKey: 'tsantaId'}); }; return Patata; }; // `app.js` // ... const models = require('./models'); // ... const run = async () => { await models.sequelize[config.postgres.sync ? 'sync' : 'authenticate'](); app.use(require('./controllers')); server.listen(config.app.port, () => { logger.info('%s: listening on %s [%sms]', config.app.name, config.app.port, Date.now() - start); }); }; run(); Σε ένα directory όλα το models. Το index διαβάζει το κάθε file και το κάνει `import`. Το export του index είναι ένα wrapper object που έχει το instance και το class. Στο app κάνει require το models (index) και πριν ξεκινήσει τον express server περιμένει το instance του sequelize να κάνει την δουλειά του. Ok, για αυτό που θες εσύ, αντί να κάνεις export functions και objects όπως εγώ, κάνε τα wrap σε classes και προσάρμοσε αντίστοιχα τα require σου (και το `forEach` στο `readdirSync`, που υποθέτω θα το μετακινήσεις στον constructor). Αφού ξεκαθάρισα τελικά τις (α) και (γ) απορίες μου, προσπαθώ να υλοποιήσω τα παραδείγματά σου με ES6 κλάσεις. Πριν από αυτό όμως θα ήθελα να αποσαφηνίσω τη λειτουργεία του sequelize.pool, και ιδιαίτερα των ιδιοτήτων max και acquire. To idle κατάλαβα τι κάνει. Για το acquire δεν βρήκα κάτι το διαφωτιστικό - τι κάνει; Και το πιο σημαντικό απ' όλα... τι πρέπει να γνωρίζω για το max; Αν καταλαβαίνω σωστά το `max: 5` σημαίνει ότι οι μέγιστες δυνατές συνδέσεις με τη βάση δεδομένων θα είναι 5 και συνεπώς ότι ο server θα υποστηρίζει μέχρι 5 παράλληλα requests (αν δηλαδή υποθέσουμε ότι όλα χρειάζονται τη βάση);;; Δεν είμαι σίγουρος με ποιο σκεπτικό πρέπει να θέσω την τιμή του max. Αν π.χ. έχω ένα forum με 1000 χρήστες online (συνδεδεμένοι + επισκέπτες + spiders) τότε θα πρέπει να βάλω κάτι παραπάνω από 1000 ως τιμή του max;;; Μια πρώτη προσπάθεια μετατροπής του κώδικά σου σε κλάσεις: Spoiler // `models/index.js` const Sequelize = require('sequelize'); const FS = require('fs'); const Path = require('path'); const config = require('../config'); class Database { constructor(...) { const sequelize = new Sequelize(...); const dbModels = {}; FS.readdirSync(__dirname) .filter(function (file) { return (file.indexOf(".") !== 0) && (file !== "index.js"); }) .forEach(function (file) { const model = sequelize.import(Path.join(__dirname, file)).init; dbModels[model.name] = model; }); Object.keys(dbModels).forEach(function (modelName) { if ("associate" in dbModels[modelName]) { dbModels[modelName].associate(dbModels); } }); dbModels.sequelize = sequelize; this.dbModels = dbModels; this.Sequelize = Sequelize; } set dbModels(object) { this._dbModels = object; } get dbModels() { return this._dbModels; } set Sequelize(orm) { this._Sequelize = orm; } get Sequelize() { return this._Sequelize; } } module.exports = Database; // `models/patata.js` class Patata { static init(sequelize, DataTypes) { let model = sequelize.define("Patata", {...}); return model; } static associate(models) { this.belongsTo(models.Tsanta, {foreignKey: 'tsantaId'}); } } module.exports = Patata; Νομίζω ότι πλησιάζω στο να κατανοήσω το πως θα δουλεύει η όλη φάση με Sequelize Models και κλάσεις αλλά χρειάζομαι λίγη βοήθεια σε κάποια σημεία για να κάνω την μετατροπή σε κλάσεις. Δυστυχώς έχω βρει ελάχιστα παραδείγματα με ES6 κλάσεις. Ένα που μου φαίνεται καλό είναι αυτό: https://codewithhugo.com/using-es6-classes-for-sequelize-4-models/ (Εάν καταφέρω να μετατρέψω τον κώδικά σου σε κλάσεις, ίσως μετά κάνω λίγο refactoring και αντικαταστήσω το import με το init.) Αυτό που με μπερδεύει αρκετά είναι το να προσαρμόσω την γραμμή `db.sequelize = sequelize;` ... όπου στο object με τα models βάζεις και τη σύνδεση με τη βάση. Έτσι όπως τα έκανα παραπάνω, στο app.js θα πρέπει για να έχω το αντίστοιχο αποτέλεσμα να κάνω κάτι τέτοιο; const DatabaseClass = require('./models'), Database = new DatabaseClass(); const models = Database.dbModels; Επεξ/σία 17 Ιουλίου 2018 από precursor
paparovic Δημοσ. 17 Ιουλίου 2018 Δημοσ. 17 Ιουλίου 2018 Τι κάνει το acquire το γράφει εδώ: http://docs.sequelizejs.com/class/lib/sequelize.js~Sequelize.html#instance-constructor-constructor To max pool βάλτο κάτω από 100. 1
Maniakos Δημοσ. 19 Ιουλίου 2018 Δημοσ. 19 Ιουλίου 2018 (επεξεργασμένο) Στις 30/6/2018 στις 9:34 ΜΜ, precursor είπε 3) Το Sequelize.sync() το οποίο συγχρονίζει τα objects των μοντέλων με τους αντίστοιχους πίνακες στη βάση, πού και πόσες φορές πρέπει να τρέξει;;; Προσωπικά μου λειτουργεί μια χαρά η εφαρμογή με το να το τρέχω κάθε φορά που χρησιμοποιώ κάποιο μοντέλο μέσω κάποιου controller. Όπως θα είδατε στον κώδικα που παρέθεσα, σε κάθε request τρέχει το new Sequelize() για νέα σύνδεση με τη βάση, το Sequelize.define() για ορισμό του model και το Sequelize.sync() για τον συγχρονισμό του με τη βάση. Απ' ό,τι διάβασα όμως, τα define και sync αρκεί να τρέξουν μία μόνο φορά κατά τη διάρκεια εκτέλεσης της εφαρμογής (π.χ. στο app.js), και το ORM θα μπορεί να δουλέψει με τους πίνακες της βάσης καθ' όλη τη διάρκεια ζωής της εφαρμογής. Εάν γνωρίζετε από Sequelize και αν το συνδυάζετε με ES6 κλάσεις θα με ενδιέφερε να μου πείτε πως το χρησιμοποιείτε εσείς! Το Sequelize.sync() δεν είναι recommended για production από την στιγμή που πιθανόν θα χρειαστείς structure alterations, αλλά για development purposes. Ο προτεινόμενος τρόπος είναι migrations. Aν θές να τα κάνεις προγραμματιστικά αντί για το sequelize-cli τότε παίζεις με uzmug (το οποίο το έχουνε φτιάξει οι τύποι που φτιάξαν το sequelize) http://docs.sequelizejs.com/class/lib/sequelize.js~Sequelize.html#instance-method-sync Αναφορά σε κείμενο options.alter Alters tables to fit models. Not recommended for production use. Deletes data in columns that were removed or had their type changed in the model. Επεξ/σία 19 Ιουλίου 2018 από Maniakos
Προτεινόμενες αναρτήσεις
Δημιουργήστε ένα λογαριασμό ή συνδεθείτε για να σχολιάσετε
Πρέπει να είστε μέλος για να αφήσετε σχόλιο
Δημιουργία λογαριασμού
Εγγραφείτε με νέο λογαριασμό στην κοινότητα μας. Είναι πανεύκολο!
Δημιουργία νέου λογαριασμούΣύνδεση
Έχετε ήδη λογαριασμό; Συνδεθείτε εδώ.
Συνδεθείτε τώρα