Πώς να χρησιμοποιήσετε το Sequelize με το Node.js και το MySQL


Ο συγγραφέας επέλεξε το Ταμείο Ανοιχτού Διαδικτύου/Ελευθερίας του Λόγου για να λάβει μια δωρεά στο πλαίσιο του προγράμματος Γράψε για Δωρεές.

Εισαγωγή

Το Sequelize είναι ένας Object Relational Mapper βασισμένος σε Node.js που καθιστά εύκολη τη δουλειά με βάσεις δεδομένων MySQL, MariaDB, SQLite, PostgreSQL και άλλες. Ένας Object Relational Mapper εκτελεί λειτουργίες όπως η διαχείριση εγγραφών βάσης δεδομένων αναπαριστώντας τα δεδομένα ως αντικείμενα. Το Sequelize διαθέτει ένα ισχυρό μηχανισμό μετανάστευσης που μπορεί να μετατρέψει υπάρχουσες δομές βάσης δεδομένων σε νέες εκδόσεις. Συνολικά, το Sequelize παρέχει εξαιρετική υποστήριξη για συγχρονισμό βάσεων δεδομένων, eager loading, συσχετίσεις, συναλλαγές και μετανάστευση βάσεων δεδομένων, ενώ μειώνει τον χρόνο ανάπτυξης και αποτρέπει τις SQL injections.

Σε αυτό το σεμινάριο, θα εγκαταστήσετε και θα διαμορφώσετε το Sequelize με MySQL στο τοπικό σας περιβάλλον ανάπτυξης. Στη συνέχεια, θα χρησιμοποιήσετε το Sequelize για να δημιουργήσετε βάσεις δεδομένων και μοντέλα, καθώς και να εκτελέσετε τις λειτουργίες εισαγωγής, επιλογής και διαγραφής. Στη συνέχεια, θα δημιουργήσετε συσχετίσεις Sequelize για σχέσεις ένα προς ένα, ένα προς πολλά και πολλά προς πολλά. Τέλος, θα δημιουργήσετε Sequelize raw queries για αντικαταστάσεις πινάκων και αντικειμένων. Εκτός από αυτά τα βασικά, το σεμινάριο καλύπτει επίσης την ασφαλή διαμόρφωση της βάσης δεδομένων χρησιμοποιώντας μεταβλητές περιβάλλοντος, τη διαχείριση των αλλαγών σχήματος με ασφάλεια μέσω μετεγκαταστάσεων και τις βέλτιστες πρακτικές για την αντιμετώπιση προβλημάτων και τη βελτιστοποίηση απόδοσης.

Αναπτύξτε τις εφαρμογές frontend σας από το GitHub χρησιμοποιώντας την πλατφόρμα εφαρμογών Linux-Console.net. Αφήστε το Linux-Console.net να επικεντρωθεί στην κλιμάκωση της εφαρμογής σας.

Κύρια Συμπεράσματα:

  • Το Sequelize παρέχει έναν εύκολο τρόπο αλληλεπίδρασης με το MySQL χρησιμοποιώντας μοντέλα αντί για άμεσες εντολές SQL, καθιστώντας τις λειτουργίες της βάσης δεδομένων πιο απλές και οργανωμένες.
  • Η αποθήκευση των διαπιστευτηρίων βάσης δεδομένων σε μεταβλητές περιβάλλοντος διατηρεί τις ευαίσθητες πληροφορίες ασφαλείς και εκτός του ελέγχου εκδόσεων.
  • Η χρήση μεταναστεύσεων για ενημερώσεις σχήματος είναι πιο ασφαλής από την εξάρτηση από το sequelize.sync(), ιδίως σε περιβάλλοντα παραγωγής.
  • Το Sequelize καθιστά εύκολο τον ορισμό σχέσεων ένα-προς-ένα, ένα-προς-πολλά και πολλά-προς-πολλά μεταξύ μοντέλων.
  • Οι άμεσες ερωτήσεις SQL μπορούν ακόμα να χρησιμοποιηθούν όταν χρειάζεστε περισσότερη έλεγχο ή καλύτερη απόδοση για σύνθετες λειτουργίες βάσεων δεδομένων.
  • Τα πιο συνηθισμένα προβλήματα του Sequelize, όπως αποτυχίες σύνδεσης ή σφάλματα μετεγκατάστασης, μπορούν να επιλυθούν ελέγχοντας τις μεταβλητές περιβάλλοντος, αναθεωρώντας τα αρχεία καταγραφής και χρησιμοποιώντας εργαλεία MySQL όπως τα EXPLAIN και SHOW PROCESSLIST.
  • Η απόδοση μπορεί να βελτιωθεί με τη βελτιστοποίηση των ερωτημάτων, την προσθήκη κατάλληλων δεικτών, τη ρύθμιση των συνδέσεων και την αποθήκευση στη μνήμη των συχνά προσπελαυσμένων δεδομένων.
  • Ο έλεγχος μεταναστεύσεων, η προσθήκη διαχείρισης σφαλμάτων και η παρακολούθηση της απόδοσης της βάσης δεδομένων βοηθά στη διατήρηση των εφαρμογών Sequelize αξιόπιστων και έτοιμων για παραγωγή.

Προαπαιτούμενα

Για να ολοκληρώσετε αυτό το σεμινάριο, θα χρειαστείτε:

  • Ένα περιβάλλον ανάπτυξης που τρέχει Node.js. Για να το ρυθμίσετε, ακολουθήστε τον οδηγό Πώς να Εγκαταστήσετε το Node.js και να Δημιουργήσετε Ένα Τοπικό Περιβάλλον Ανάπτυξης για το λειτουργικό σας σύστημα.
  • Το MySQL είναι εγκατεστημένο στο περιβάλλον εργασίας σας. Ακολουθήστε τον οδηγό Πώς να Εγκαταστήσετε το MySQL για το περιβάλλον σας, συμπεριλαμβανομένων των βημάτων για τη δημιουργία ενός χρήστη.
  • Γνωριμία με τη JavaScript και τις ερωτήσεις MySQL, τις οποίες μπορείτε να αναπτύξετε με τη σειρά How To Code in JavaScript και το σεμινάριο Μία Εισαγωγή στις Ερωτήσεις στο MySQL.
  • Μια βασική κατανόηση των εννοιών των σχεσιακών βάσεων δεδομένων, την οποία μπορείτε να βρείτε στο σεμινάριο, Κατανόηση Σχεσιακών Βάσεων Δεδομένων.

Αυτό το σεμινάριο δοκιμάστηκε στην έκδοση Node.js v24.11.1 και στην έκδοση npm 11.6.2.

Εγκατάσταση και Διαμόρφωση του Sequelize

Σε αυτό το βήμα, θα εγκαταστήσετε το Sequelize και θα δημιουργήσετε τη σύνδεση με τη βάση δεδομένων MySQL σας. Για να το κάνετε αυτό, πρώτα θα δημιουργήσετε μια εφαρμογή Node.js. Στη συνέχεια, θα εγκαταστήσετε το Sequelize, θα ρυθμίσετε τη βάση δεδομένων MySQL και θα αναπτύξετε μια απλή εφαρμογή.

Εγκατάσταση του Sequelize

Ξεκινήστε δημιουργώντας έναν φάκελο για το έργο. Σε αυτό το παράδειγμα, μπορείτε να χρησιμοποιήσετε το hello-world. Αφού δημιουργηθεί ο φάκελος, πλοηγηθείτε στον φάκελο χρησιμοποιώντας το τερματικό:

mkdir hello-world

cd hello-world

Στη συνέχεια, δημιουργήστε ένα δείγμα εφαρμογής Node.js χρησιμοποιώντας την ακόλουθη εντολή:

npm init

Στη συνέχεια, θα σας ζητηθεί να απαντήσετε σε μερικές ερωτήσεις ρύθμισης. Χρησιμοποιήστε την παρακάτω έξοδο για τη διαμόρφωσή σας. Πατήστε ENTER για να χρησιμοποιήσετε την προεπιλεγμένη τιμή που εμφανίζεται και βεβαιωθείτε ότι έχετε ορίσει το κύριο σημείο εισόδου ως server.js. Αυτό δημιουργεί μια δομή έργου που είναι εύκολη στη συντήρηση.

Η έξοδος θα μοιάζει ως εξής, και θα γεμίσει το αρχείο package.json:

{
  "name": "hello-world",
  "version": "1.0.0",
  "description": "",
  "main": "server.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC"
}

Στη συνέχεια, δημιουργήστε ένα κενό αρχείο server.js μέσα στον φάκελο του έργου:

touch server.js

Αφού ακολουθήσετε τα προηγούμενα βήματα, η τελική δομή των φακέλων σας θα μοιάζει με αυτή:

hello-world/
├─ package.json
├─ server.js

Τώρα μπορείτε να εγκαταστήσετε το Sequelize με την ακόλουθη εντολή:

npm i sequelize

Μετά από αυτές τις ενημερώσεις, το αρχείο package.json φαίνεται πλέον έτσι:

{
  "name": "hello-world",
  "version": "1.0.0",
  "description": "",
  "main": "server.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "node server.js"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "sequelize": "^6.37.7"
  }
}

Στην ενότητα dependencies, θα δείτε τώρα μια εξάρτηση Sequelize.

Έχετε στήσει το έργο και έχετε εγκαταστήσει το Sequelize. Στη συνέχεια, θα δημιουργήσετε μια δοκιμαστική βάση δεδομένων για να τη συνδέσετε.

Δημιουργία ενός Δείγματος Βάσης Δεδομένων

Στο πλαίσιο των προαπαιτούμενων, εγκαταστήσατε και διαμορφώσατε το MySQL, το οποίο περιλάμβανε τη δημιουργία χρήστη. Τώρα θα δημιουργήσετε μια κενή βάση δεδομένων.

Για να το κάνετε αυτό, πρώτα πρέπει να συνδεθείτε στη MySQL σας. Εάν εργάζεστε απομακρυσμένα, μπορείτε να χρησιμοποιήσετε το εργαλείο της επιλογής σας. Εάν χρησιμοποιείτε μια τοπικά εγκατεστημένη MySQL, μπορείτε να χρησιμοποιήσετε την ακόλουθη εντολή, αντικαθιστώντας το your_username με το όνομα χρήστη σας στο MySQL:

mysql -u your_username -p

-u είναι το όνομα χρήστη και η επιλογή -p χρησιμοποιείται αν ο λογαριασμός προστατεύεται με κωδικό πρόσβασης.

Ο διακομιστής MySQL θα ζητήσει τον κωδικό πρόσβασης της βάσης δεδομένων σας. Πληκτρολογήστε τον κωδικό σας και πατήστε ENTER.

Μόλις συνδεθείτε, δημιουργήστε μια βάση δεδομένων με όνομα hello_world_db χρησιμοποιώντας την ακόλουθη εντολή:

CREATE DATABASE hello_world_db;

Για να επαληθεύσετε εάν έχετε δημιουργήσει επιτυχώς τη βάση δεδομένων, μπορείτε να χρησιμοποιήσετε αυτήν την εντολή:

SHOW DATABASES;

Η έξοδός σας θα είναι παρόμοια με αυτή:

+--------------------+
|      Database      |
+--------------------+
| hello_world_db     |
| information_schema |
| mysql              |
| performance_schema |
| sys                |
+--------------------+

Μετά τη δημιουργία της δείγματικής βάσης δεδομένων, αποσυνδεθείτε από τον διακομιστή MySQL:

mysql> QUIT

Τώρα, πρέπει να εγκαταστήσετε έναν χειροκίνητο οδηγό για τη βάση δεδομένων της επιλογής σας. Δεδομένου ότι το Sequelize παρέχει μόνο δυνατότητες ORM, δεν περιλαμβάνει ενσωματωμένους οδηγούς βάσεων δεδομένων. Επομένως, θα χρειαστεί να εγκαταστήσετε τους οδηγούς σύμφωνα με την προτίμησή σας. Για να το κάνετε αυτό, πλοηγηθείτε στον κατάλογο του έργου χρησιμοποιώντας το τερματικό και εγκαταστήστε τον οδηγό MySQL στο έργο χρησιμοποιώντας την ακόλουθη εντολή:

npm install --save mysql2

Σε αυτή την περίπτωση, χρησιμοποιείτε τον οδηγό για MySQL.

Σημείωση: Δεδομένου ότι αυτός ο οδηγός χρησιμοποιεί MySQL ως βάση δεδομένων, χρησιμοποιείτε έναν οδηγό για αυτήν. Ανάλογα με τη βάση δεδομένων σας, μπορείτε να εγκαταστήσετε τον οδηγό χειροκίνητα ως εξής:

  • npm install --save pg pg-hstore # Postgres
  • npm install --save mysql2
  • npm install --save mariadb
  • npm install --save sqlite3
  • npm install --save tedious # Microsoft SQL Server

Τώρα που έχετε μια δείγμα βάσης δεδομένων, μπορείτε να δημιουργήσετε την πρώτη σας εφαρμογή Sequelize με σύνδεση στη βάση δεδομένων.

Σύνδεση με τη βάση δεδομένων MySQL

Σε αυτή την ενότητα, θα συνδέσετε την εφαρμογή Node.js με τη βάση δεδομένων MySQL χρησιμοποιώντας το Sequelize.

Για να συνδεθείτε με τη βάση δεδομένων, ανοίξτε το server.js για επεξεργασία χρησιμοποιώντας το nano ή τον προτιμώμενό σας επεξεργαστή κώδικα:

nano server.js

Εδώ, θα δημιουργήσετε μια σύνδεση βάσης δεδομένων στην εφαρμογή σας χρησιμοποιώντας ένα παράδειγμα Sequelize. Στη μέθοδο new Sequelize(), περάστε τις παραμέτρους του διακομιστή MySQL και τα στοιχεία σύνδεσης της βάσης δεδομένων ως εξής, αντικαθιστώντας τα DATABASE_USERNAME και DATABASE_PASSWORD με τα στοιχεία του χρήστη MySQL σας:

const Sequelize = require("sequelize");
const sequelize = new Sequelize(
 'hello_world_db',
 'DATABASE_USERNAME',
 'DATABASE_PASSWORD',
  {
    host: 'DATABASE_HOST',
    dialect: 'mysql'
  }
);

host είναι ο τόπος όπου φιλοξενείται ο διακομιστής MySQL, επομένως θα χρειαστεί να παρέχετε μια διεύθυνση URL διακομιστή ή μια διεύθυνση IP. Αν χρησιμοποιείτε έναν τοπικά εγκατεστημένο διακομιστή MySQL, μπορείτε να αντικαταστήσετε το DATABASE_HOST με localhost ή 127.0.0.1 ως τιμή.

Ομοίως, εάν χρησιμοποιείτε έναν απομακρυσμένο διακομιστή, βεβαιωθείτε ότι αντικαθιστάτε τις τιμές σύνδεσης της βάσης δεδομένων ανάλογα με τα κατάλληλα στοιχεία του απομακρυσμένου διακομιστή.

Σημείωση: Εάν χρησιμοποιείτε οποιοδήποτε άλλο λογισμικό διακομιστή βάσεων δεδομένων, μπορείτε να αντικαταστήσετε την παράμετρο διαλέκτου αντίστοιχα.

Στη συνέχεια, καλέστε μια μέθοδο authenticate() που βασίζεται σε υποσχέσεις για να δημιουργήσετε μια σύνδεση με τη βάση δεδομένων για την εφαρμογή. Για να το κάνετε αυτό, προσθέστε το ακόλουθο μπλοκ κώδικα στο αρχείο server.js σας:

...

sequelize.authenticate().then(() => {
   console.log('Connection has been established successfully.');
}).catch((error) => {
   console.error('Unable to connect to the database: ', error);
});

Η μέθοδος authenticate() χρησιμοποιείται για τη σύνδεση με τη βάση δεδομένων και ελέγχει αν τα παρεχόμενα διαπιστευτήρια είναι σωστά. Εδώ, η σύνδεση με τη βάση δεδομένων είναι ανοιχτή από προεπιλογή και η ίδια σύνδεση μπορεί να χρησιμοποιηθεί για όλες τις ερωτήσεις. Όποτε χρειάζεται να κλείσετε τη σύνδεση, καλέστε τη μέθοδο sequelize.close() μετά από αυτήν την κλήση authenticate(). Για να μάθετε περισσότερα για το Sequelize, δείτε τον οδηγό τους για αρχάριους.

Οι περισσότερες από τις μεθόδους που παρέχει το Sequelize είναι ασύγχρονες. Αυτό σημαίνει ότι μπορείτε να εκτελείτε διαδικασίες στην εφαρμογή σας ενώ ένα ασύγχρονο τμήμα κώδικα βρίσκεται σε φάση εκτέλεσης. Επιπλέον, μετά την επιτυχή εκτέλεση του ασύγχρονου κώδικα, επιστρέφει μια υπόσχεση (promise), που είναι η τιμή που επιστρέφεται στο τέλος μιας διαδικασίας. Επομένως, σε ασύγχρονα τμήματα κώδικα, μπορείτε να χρησιμοποιείτε then(), catch() και finally() για να επιστρέψετε τα επεξεργασμένα δεδομένα.

Σε αυτό το σημείο, το αρχείο server.js θα φαίνεται ως εξής:

const Sequelize = require("sequelize");

const sequelize = new Sequelize(
   'hello_world_db',
   'DATABASE_USERNAME',
   'DATABASE_PASSWORD',
    {
      host: 'DATABASE_HOST',
      dialect: 'mysql'
    }
  );

sequelize.authenticate().then(() => {
   console.log('Connection has been established successfully.');
}).catch((error) => {
   console.error('Unable to connect to the database: ', error);
});

Αποθήκευσε και κλείσε το αρχείο σου.

Στον φάκελο του έργου, εκτελέστε την εφαρμογή server.js εκτελώντας την ακόλουθη εντολή:

node server.js

Η έξοδός σας θα μοιάζει έτσι:

Connection has been established successfully!

Έχετε δημιουργήσει επιτυχώς τη σύνδεση με τη βάση δεδομένων.

Σε αυτό το βήμα, εγκαταστήσατε το Sequelize, δημιουργήσατε μια δοκιμαστική βάση δεδομένων και χρησιμοποιήσατε το Sequelize για να συνδεθείτε με τη βάση δεδομένων. Στη συνέχεια, θα εργαστείτε με μοντέλα στο Sequelize.

Δημιουργία Πίνακα Βάσης Δεδομένων με χρήση του Sequelize

Τώρα που έχετε δημιουργήσει μια δείγμα βάσης δεδομένων MySQL, μπορείτε να χρησιμοποιήσετε το Sequelize για να δημιουργήσετε έναν πίνακα και να τον γεμίσετε με δεδομένα. Στο Sequelize, οι πίνακες βάσεων δεδομένων αναφέρονται ως μοντέλα. Ένα μοντέλο είναι μια αφαίρεση που αντιπροσωπεύει έναν πίνακα της βάσης δεδομένων. Τα μοντέλα καθορίζουν διάφορα πράγματα στο Sequelize, όπως το όνομα του πίνακα, λεπτομέρειες των στηλών και τύπους δεδομένων. Σε αυτό το βήμα, θα δημιουργήσετε ένα μοντέλο Sequelize για δεδομένα βιβλίου.

Για να ξεκινήσετε, δημιουργήστε ένα νέο αρχείο με όνομα book.model.js στον φάκελο του έργου:

nano book.model.js

Παρόμοια με το προηγούμενο βήμα, προσθέστε τον κώδικα του Sequelize για την εκκίνηση της βάσης δεδομένων με μια νέα εισαγωγή για το DataTypes στην κορυφή του αρχείου:

const { Sequelize, DataTypes } = require("sequelize");

Το Sequelize περιέχει πολλούς ενσωματωμένους τύπους δεδομένων. Για να αποκτήσετε πρόσβαση σε αυτούς τους τύπους δεδομένων, προσθέτετε μια εισαγωγή για το DataTypes. Αυτός ο οδηγός αναφέρεται σε μερικούς συχνά χρησιμοποιούμενους τύπους δεδομένων, όπως STRING, INTEGER και DATEONLY. Για να μάθετε περισσότερα για άλλους υποστηριζόμενους τύπους δεδομένων, μπορείτε να ανατρέξετε στην επίσημη τεκμηρίωση του Sequelize.

Στη συνέχεια, συμπεριλάβετε τις γραμμές που χρησιμοποιήσατε προηγουμένως για να δημιουργήσετε μια σύνδεση στη βάση δεδομένων MySQL σας, ενημερώνοντας τα διαπιστευτήρια MySQL σας ανάλογα:

...

const sequelize = new Sequelize(
   'hello_world_db',
   'DATABASE_USERNAME',
   'DATABASE_PASSWORD',
    {
      host: 'DATABASE_HOST',
      dialect: 'mysql'
    }
  );

sequelize.authenticate().then(() => {
   console.log('Connection has been established successfully.');
}).catch((error) => {
   console.error('Unable to connect to the database: ', error);
});

Στη συνέχεια, θα δημιουργήσετε ένα μοντέλο με όνομα books, το οποίο περιλαμβάνει title, author, release_date και subject ID. Για να το κάνετε αυτό, χρησιμοποιήστε τη μέθοδο sequelize.define() όπως φαίνεται:

...

const Book = sequelize.define("books", {
   title: {
     type: DataTypes.STRING,
     allowNull: false
   },
   author: {
     type: DataTypes.STRING,
     allowNull: false
   },
   release_date: {
     type: DataTypes.DATEONLY,
   },
   subject: {
     type: DataTypes.INTEGER,
   }
});

Η μέθοδος sequelize.define() ορίζει ένα νέο μοντέλο, το οποίο αντιπροσωπεύει έναν πίνακα στη βάση δεδομένων. Αυτό το μπλοκ κώδικα δημιουργεί έναν πίνακα με όνομα books και αποθηκεύει τις εγγραφές βιβλίων σύμφωνα με τα title, author, release_date και subject.

Σε αυτόν τον κώδικα, το allowNull δείχνει ότι η τιμή της στήλης του μοντέλου δεν μπορεί να είναι null. Ομοίως, αν χρειαστεί να ορίσετε μια τέτοια τιμή, μπορείτε να χρησιμοποιήσετε το defaultValue: "value".

Στη συνέχεια, θα προσθέσετε το μοντέλο book στη βάση δεδομένων σας. Για να το κάνετε αυτό, θα χρησιμοποιήσετε τη μέθοδο sync() ως εξής:

...

sequelize.sync().then(() => {
   console.log('Book table created successfully!');
}).catch((error) => {
   console.error('Unable to create table : ', error);
});

Στη μέθοδο sync(), ζητάς από το Sequelize να κάνει μερικά πράγματα στη βάση δεδομένων. Με αυτό το κάλεσμα, το Sequelize θα εκτελέσει αυτόματα ένα ερώτημα SQL στη βάση δεδομένων και θα δημιουργήσει έναν πίνακα, εμφανίζοντας το μήνυμα Ο πίνακας βιβλίων δημιουργήθηκε με επιτυχία!.

Όπως αναφέρθηκε, η μέθοδος sync() βασίζεται σε υποσχέσεις (promise), πράγμα που σημαίνει ότι μπορεί επίσης να εκτελέσει χειρισμό σφαλμάτων. Σε αυτό το μπλοκ κώδικα, θα ελέγξετε εάν ο πίνακας δημιουργήθηκε επιτυχώς. Αν όχι, θα επιστρέψει ένα σφάλμα μέσω της μεθόδου catch και θα το εμφανίσει στην έξοδο.

Σημείωση: Μπορείτε να διαχειριστείτε τον συγχρονισμό μοντέλων περνώντας παραμέτρους force για να αναγκάσετε τη δημιουργία ενός νέου πίνακα αν δεν υπάρχει, ή να χρησιμοποιήσετε έναν υπάρχοντα. Εδώ είναι μερικά παραδείγματα που μπορεί να σας φανούν χρήσιμα όταν εργάζεστε με το Sequelize:

  • model.sync(): Αυτό δημιουργεί τον πίνακα αν δεν υπάρχει ήδη.
  • model.sync({ force: true }): Αυτό δημιουργεί τον πίνακα διαγράφοντάς τον αν υπάρχει ήδη πίνακας με το ίδιο όνομα.

Ο τελικός κώδικας θα μοιάζει έτσι:

const {Sequelize, DataTypes} = require("sequelize");

const sequelize = new Sequelize(
   'hello_world_db',
   'DATABASE_USERNAME',
   'DATABASE_PASSWORD',
    {
      host: 'DATABASE_HOST',
      dialect: 'mysql'
    }
  );

sequelize.authenticate().then(() => {
   console.log('Connection has been established successfully.');
}).catch((error) => {
   console.error('Unable to connect to the database: ', error);
});

const Book = sequelize.define("books", {
   title: {
     type: DataTypes.STRING,
     allowNull: false
   },
   author: {
     type: DataTypes.STRING,
     allowNull: false
   },
   release_date: {
     type: DataTypes.DATEONLY,
   },
   subject: {
     type: DataTypes.INTEGER,
   }
});

sequelize.sync().then(() => {
   console.log('Book table created successfully!');
}).catch((error) => {
   console.error('Unable to create table : ', error);
});

Αποθήκευσε και κλείσε το αρχείο σου.

Τρέξτε την εφαρμογή σας χρησιμοποιώντας την ακόλουθη εντολή:

node book.model.js

Θα λάβετε την εξής έξοδο στη γραμμή εντολών σας:

Executing (default): SELECT 1+1 AS result
Executing (default): CREATE TABLE IF NOT EXISTS `books` (`id` INTEGER NOT NULL auto_increment , `title` VARCHAR(255) NOT NULL, `author` VARCHAR(255) NOT NULL, `release_date` DATE, `subject` INTEGER, `createdAt` DATETIME NOT NULL, `updatedAt` DATETIME NOT NULL, PRIMARY KEY (`id`)) ENGINE=InnoDB;
Connection has been established successfully.
Executing (default): SHOW INDEX FROM `books`
Book table created successfully!

Στην έξοδο, θα δείτε ότι το αρχείο καταγραφής επιστροφής περιέχει το μήνυμα, Ο πίνακας βιβλίων δημιουργήθηκε με επιτυχία!. Μπορείτε να το επαληθεύσετε ελέγχοντας τη βάση δεδομένων σας για να δείτε τον νέο πίνακα books που δημιουργήθηκε στη βάση δεδομένων hello_world_db.

Για να επαληθεύσετε τη δημιουργία του νέου πίνακα, συνδεθείτε στην περίπτωση MySQL σας:

mysql -u YOUR_USERNAME -p

Μετά την εισαγωγή του κωδικού σας, αλλάξτε στη βάση δεδομένων δείγματος:

USE hello_world_db;

Και στη συνέχεια τρέξτε την εντολή για να εμφανίσετε τους πίνακες:

SHOW TABLES;

Η έξοδός σας θα είναι παρόμοια με αυτή:

+---------------------------+
| Tables_in_hello_world_db |
+---------------------------+
| books                     |
+---------------------------+
1 row in set (0.00 sec)

Τέλος, αποσυνδεθείτε από τον διακομιστή MySQL:

mysql> QUIT

Έχετε επιβεβαιώσει ότι η δημιουργία του μοντέλου book ήταν επιτυχής. Χρησιμοποιώντας αυτή τη διαδικασία, μπορείτε να δημιουργήσετε οποιονδήποτε αριθμό μοντέλων ακολουθώντας την ίδια διαδικασία.

Σε αυτό το βήμα, δημιουργήσατε ένα μοντέλο σε μια βάση δεδομένων και ξεκινήσατε να εργάζεστε με ένα μοντέλο χρησιμοποιώντας ενσωματωμένες μεθόδους. Επίσης, χρησιμοποιήσατε τύπους δεδομένων που υποστηρίζονται από το Sequelize για να ορίσετε το μοντέλο σας. Στη συνέχεια, θα εργαστείτε με βασικά ερωτήματα μοντέλου.

Χρήση του Sequelize για Ερωτήματα Βάσης Δεδομένων

Σε αυτό το βήμα, θα χρησιμοποιήσετε τις ενσωματωμένες ερωτήσεις του Sequelize για εισαγωγή, επιλογή, επιλογή με συνθήκες και διαγραφή.

Εισαγωγή νέας εγγραφής

Στο προηγούμενο βήμα, δημιουργήσατε ένα μοντέλο book μέσα στη βάση δεδομένων. Σε αυτήν την ενότητα, θα εισαγάγετε δεδομένα σε αυτό το μοντέλο.

Για να ξεκινήσετε, αντιγράψτε τα περιεχόμενα του book.model.js από το προηγούμενο βήμα. Δημιουργήστε ένα νέο αρχείο με όνομα book.controller.js για να χειριστείτε τη λογική των ερωτημάτων. Προσθέστε τον κώδικα από το book.model.js στο book.controller.js.

Στο book.controller.js, εντοπίστε τη μέθοδο sync(). Στη μέθοδο sync(), προσθέστε τις παρακάτω επισημασμένες γραμμές:

...

sequelize.sync().then(() => {
   console.log('Book table created successfully!');

   Book.create({
       title: "Clean Code",
       author: "Robert Cecil Martin",
       release_date: "2021-12-14",
       subject: 3
   }).then(res => {
       console.log(res)
   }).catch((error) => {
       console.error('Failed to create a new record : ', error);
   });

}).catch((error) => {
   console.error('Unable to create table : ', error);
});

Εδώ, εισάγετε μια νέα εγγραφή βιβλίου στο μοντέλο books που έχετε ήδη δημιουργήσει χρησιμοποιώντας τη μέθοδο sync(), η οποία υποστηρίζει την προσθήκη νέων εγγραφών σε προϋπάρχοντα μοντέλα. Μόλις η μέθοδος sync() εκτελεστεί επιτυχώς, εκτελεί τη μέθοδο then(). Μέσα στη μέθοδο then(), καλείτε τη μέθοδο create() για να εισάγετε τις νέες εγγραφές στο μοντέλο.

Χρησιμοποιείτε τη μέθοδο create() για να περάσετε τα δεδομένα που χρειάζεστε να προσθέσετε στη βάση δεδομένων ως αντικείμενο. Το επισημασμένο τμήμα κώδικα θα εισαγάγει μια νέα εγγραφή στον υπάρχοντα πίνακα books. Σε αυτό το παράδειγμα, προσθέτετε το Clean Code του Robert Cecil Martin, το οποίο έχει κατηγοριοποιηθεί με το subject ID 3. Μπορείτε να χρησιμοποιήσετε τον ίδιο κώδικα, ενημερωμένο με πληροφορίες για άλλα βιβλία, για να προσθέσετε νέες εγγραφές στη βάση δεδομένων σας.

Αποθήκευσε και κλείσε το αρχείο.

Τρέξτε την εφαρμογή χρησιμοποιώντας την ακόλουθη εντολή:

node book.controller.js

Η έξοδός σας θα μοιάζει με την ακόλουθη:

books {
  dataValues:
   { id: 1,
     title: 'Clean Code',
     author: 'Robert Cecil Martin',
     release_date: '2021-12-14',
     subject: 3,
     updatedAt: 2021-12-14T10:12:16.644Z,
   ...
}

Έχετε εισάγει μια νέα εγγραφή στο μοντέλο που δημιουργήσατε στη βάση δεδομένων. Μπορείτε να συνεχίσετε να προσθέτετε πολλαπλές εγγραφές χρησιμοποιώντας την ίδια διαδικασία.

Επιλογή όλων των εγγραφών

Σε αυτήν την ενότητα, θα επιλέξετε και θα πάρετε όλα τα αρχεία βιβλίων από τη βάση δεδομένων χρησιμοποιώντας τη μέθοδο findAll(). Για να το κάνετε αυτό, ανοίξτε πρώτα το book.controller.js και αφαιρέστε την προηγούμενη μέθοδο Book.create(). Στη μέθοδο sync(), προσθέστε τη μέθοδο Book.findAll() όπως φαίνεται:

...

sequelize.sync().then(() => {

    Book.findAll().then(res => {
        console.log(res)
    }).catch((error) => {
        console.error('Failed to retrieve data : ', error);
    });

}).catch((error) => {
    console.error('Unable to create table : ', error);
});

...

Αποθήκευσε και κλείσε το αρχείο.

Στη συνέχεια, εκτελέστε ξανά την εφαρμογή χρησιμοποιώντας την ακόλουθη εντολή:

node book.controller.js

Η έξοδός σας θα μοιάζει με την ακόλουθη:

[
  books {
    dataValues: {
      id: 1,
      title: 'Clean Code',
      author: 'Robert Cecil Martin',
      release_date: '2020-01-01',
      subject: 3,
      createdAt: 2021-02-22T09:13:55.000Z,
      updatedAt: 2021-02-22T09:13:55.000Z
    },
    _previousDataValues: {
      id: 1,
      title: 'Clean Code',
      author: 'Robert Cecil Martin',
      release_date: '2020-01-01',
      subject: 3,
      createdAt: 2021-02-22T09:13:55.000Z,
      updatedAt: 2021-02-22T09:13:55.000Z
    },
...
]

Η έξοδος περιέχει όλα τα δεδομένα των βιβλίων ως αντικείμενο πίνακα. Χρησιμοποιήσατε επιτυχώς τη μέθοδο findAll() του Sequelize για να επιστρέψετε όλα τα δεδομένα των βιβλίων από τη βάση δεδομένων.

Επιλογή με τη ρήτρα where

Σε αυτήν την ενότητα, θα επιλέξετε τιμές με συνθήκες χρησιμοποιώντας τη δήλωση where. Η δήλωση where χρησιμοποιείται για να καθορίσετε μια συνθήκη κατά την ανάκτηση δεδομένων. Για αυτό το μάθημα, θα πάρετε ένα βιβλίο με συγκεκριμένο αναγνωριστικό καταγραφής από τη βάση δεδομένων χρησιμοποιώντας τη μέθοδο findOne().

Για να το κάνετε αυτό, ανοίξτε το book.controller.js για επεξεργασία, διαγράψτε τη μέθοδο findAll() και προσθέστε τις ακόλουθες γραμμές:

...

sequelize.sync().then(() => {

    Book.findOne({
        where: {
            id: 1
        }
    }).then(res => {
        console.log(res)
    }).catch((error) => {
        console.error('Failed to retrieve data : ', error);
    });

}).catch((error) => {
    console.error('Unable to create table : ', error);
});

Εδώ, επιλέγετε μια συγκεκριμένη καταγραφή βιβλίου από τη βάση δεδομένων χρησιμοποιώντας τη μέθοδο findOne() με την επιλογή where. Σε αυτό το παράδειγμα, ανακτάτε τα δεδομένα του βιβλίου που το id του είναι ίσο με 1.

Αποθήκευσε και κλείσε το αρχείο.

Στη συνέχεια, εκτελέστε την εφαρμογή:

node book.controller.js

Η έξοδός σας θα μοιάζει με την ακόλουθη:

books {
  dataValues: {
    id: 1,
    title: 'Clean Code',
    author: 'Robert Cecil Martin',
    release_date: '2020-01-01',
    subject: 'Science',
    createdAt: 2021-02-22T09:13:55.000Z,
    updatedAt: 2021-02-22T09:13:55.000Z
  },
  ...
}

Έχετε χρησιμοποιήσει με επιτυχία ρήτρες where για να λάβετε δεδομένα από μοντέλα Sequelize. Μπορείτε να χρησιμοποιήσετε τη ρήτρα where στην εφαρμογή βάσης δεδομένων για να πάρτε δεδομένα υπό συνθήκη.

Διαγραφή Εγγραφής

Για να διαγράψετε μια συγκεκριμένη εγγραφή από το μοντέλο της βάσης δεδομένων, χρησιμοποιείτε τη μέθοδο destroy() με την επιλογή where. Για να το κάνετε αυτό, ανοίξτε το book.controller.js, αφαιρέστε τη μέθοδο findOne() και προσθέστε τις παρακάτω επισημασμένες γραμμές:

...
sequelize.sync().then(() => {

  Book.destroy({
      where: {
        id: 2
      }
  }).then(() => {
      console.log("Successfully deleted record.")
  }).catch((error) => {
      console.error('Failed to delete record : ', error);
  });

}).catch((error) => {
    console.error('Unable to create table : ', error);
});

Εδώ, αφαιρείτε μια εγγραφή βιβλίου από τη βάση δεδομένων χρησιμοποιώντας τη μέθοδο destroy() με την επιλογή where και δίνοντας το id του βιβλίου που θέλετε να αφαιρέσετε. Θα αφαιρέσετε την εγγραφή βιβλίου της οποίας το id είναι ίσο με 2.

Αποθήκευσε και κλείσε το αρχείο.

Στη συνέχεια, εκτελέστε την εφαρμογή:

node book.controller.js

Η έξοδός σας θα μοιάζει με το εξής:

Successfully deleted record.

Η εγγραφή έχει διαγραφεί.

Σε αυτό το βήμα, πειραματιστήκατε με το μοντέλο της βάσης δεδομένων σας και με την ερώτηση μοντέλων. Ξεκινήσατε τη βάση δεδομένων, δημιουργήσατε μοντέλα, εισαγάγατε εγγραφές, ανακτήσατε εγγραφές, ανακτήσατε εγγραφές με συνθήκες χρησιμοποιώντας την εντολή where και διαγράψατε επιλεγμένες εγγραφές. Με αυτή τη γνώση του Sequelize, θα δημιουργήσετε τώρα συσχετίσεις στο Sequelize. Μετά από αυτό, θα μπορείτε να ορίσετε και να εργαστείτε με διάφορους τύπους σχέσεων χρησιμοποιώντας μοντέλα Sequelize.

Δημιουργία Συσχετισμών χρησιμοποιώντας το Sequelize

Σε αυτό το βήμα, θα χρησιμοποιήσετε τους τυπικούς τύπους συσχετίσεων που υποστηρίζει το Sequelize: ένα προς ένα, ένα προς πολλά και πολλά προς πολλά. Θα χρησιμοποιήσετε δείγμα δεδομένων για φοιτητές, μαθήματα και επίπεδα βαθμολογίας.

Το Sequelize χρησιμοποιεί τύπους συσχετίσεων βασισμένους στις ακόλουθες σχέσεις βάσης δεδομένων:

  • μία προς μία σχέση: Μία σχέση μία προς μία σημαίνει ότι μια εγγραφή σε έναν πίνακα σχετίζεται ακριβώς με μία εγγραφή σε έναν άλλο πίνακα. Όσον αφορά το Sequelize, μπορείτε να χρησιμοποιήσετε τις συσχετίσεις belongsTo() και hasOne() για να δημιουργήσετε αυτόν τον τύπο σχέσης.

  • μία-προς-πολλές σχέση: Μία σχέση μία-προς-πολλές σημαίνει ότι μια εγγραφή σε έναν πίνακα σχετίζεται με πολλές εγγραφές σε έναν άλλο πίνακα. Με το Sequelize, μπορείτε να χρησιμοποιήσετε τις μεθόδους συσχετισμού hasMany() για να δημιουργήσετε αυτόν τον τύπο σχέσης.

  • πολλά-προς-πολλά σχέση: Μια σχέση πολλά-προς-πολλά σημαίνει ότι πολλαπλές εγγραφές σε έναν πίνακα συσχετίζονται με πολλαπλές εγγραφές σε έναν άλλο πίνακα. Με το Sequelize, μπορείτε να χρησιμοποιήσετε τις συσχετίσεις belongsToMany() για να δημιουργήσετε αυτόν τον τύπο σχέσης.

Πριν δημιουργήσετε αυτές τις συσχετίσεις, θα δημιουργήσετε πρώτα μια νέα βάση δεδομένων με όνομα student_db και θα προσθέσετε νέα μοντέλα και κάποια δείγματα δεδομένων για φοιτητές, μαθήματα και επίπεδο βαθμού.

Για να δημιουργήσετε τη βάση δεδομένων, ακολουθήστε την ίδια διαδικασία που περιγράφεται στην Εγκατάσταση και Διαμόρφωση του Sequelize για να συνδεθείτε στο MySQL και να δημιουργήσετε μια βάση δεδομένων με το όνομα student_db. Μόλις δημιουργηθεί η νέα βάση δεδομένων, αποσυνδεθείτε από το MySQL. Στη συνέχεια, θα ξεκινήσετε να δημιουργείτε συσχετίσεις στη βάση δεδομένων.

Δημιουργία Σχέσης Ένας προς Ένα με το belongsTo()

Σε αυτή την ενότητα, θα δημιουργήσετε μια σχέση ένα προς ένα χρησιμοποιώντας μοντέλα Sequelize. Φανταστείτε ότι θέλετε να λάβετε τα στοιχεία ενός μαθητή μαζί με την τάξη του. Δεδομένου ότι ένας μαθητής μπορεί να έχει μόνο μία τάξη, αυτός ο τύπος συσχέτισης είναι μια σχέση ένα προς ένα και μπορείτε να χρησιμοποιήσετε τη μέθοδο belongsTo().

Σημείωση: Υπάρχει διαφορά μεταξύ belongsTo() και hasOne(). Το belongsTo() θα προσθέσει το foreignKey στον πίνακα προέλευσης, ενώ το hasOne() θα το προσθέσει στον πίνακα-στόχο. Σε κάθε περίπτωση, αν χρησιμοποιηθούν και οι δύο σχέσεις ταυτόχρονα, θα λειτουργήσει ως διμερής σχέση ένα προς ένα στο Sequelize.

Η μέθοδος belongsTo() σας επιτρέπει να δημιουργήσετε μια σχέση ενός προς ένα μεταξύ δύο μοντέλων Sequelize. Σε αυτό το παράδειγμα, χρησιμοποιείτε τα μοντέλα Student και Grade.

Δημιουργήστε ένα νέο αρχείο με το όνομα one_to_one.js. Όπως κάνατε στην προηγούμενη ενότητα, Σύνδεση με τη Βάση Δεδομένων MySQL, προσθέστε τις γραμμές για να δημιουργήσετε μια σύνδεση με τη βάση δεδομένων και να πιστοποιήσετε τον χρήστη MySQL στην κορυφή του αρχείου. Βεβαιωθείτε ότι ενημερώνετε τα διαπιστευτήρια MySQL όπως χρειάζεται:

const { Sequelize, DataTypes } = require("sequelize");

const sequelize = new Sequelize(
   'student_db',
   'DATABASE_USERNAME',
   'DATABASE_PASSWORD',
    {
      host: 'DATABASE_HOST',
      dialect: 'mysql'
    }
  );

sequelize.authenticate().then(() => {
   console.log('Connection has been established successfully.');
}).catch((error) => {
   console.error('Unable to connect to the database: ', error);
});

Σε αυτή την ενότητα, θα δημιουργήσετε τρία μοντέλα στη νέα βάση δεδομένων student_db: Student, Grade και Course. Θα ξεκινήσετε δημιουργώντας τα μοντέλα Student και Grade. Αργότερα σε αυτό το βήμα, θα δημιουργήσετε το μοντέλο Courses.

Για το μοντέλο Student, πρόσθεσε το ακόλουθο μπλοκ κώδικα στο one_to_one.js:

...
const Student = sequelize.define("students", {
   student_id: {
       type: DataTypes.UUID,
       defaultValue: DataTypes.UUIDV4,
       primaryKey: true,
   },
   name: {
       type: DataTypes.STRING,
       allowNull: false
   }
});

Αυτό το μοντέλο φοιτητή περιέχει δύο στήλες: student_id και name.

Στη συνέχεια, προσθέστε ένα μπλοκ κώδικα για το μοντέλο Grade:

...
const Grade = sequelize.define("grades", {
   grade: {
       type: DataTypes.INTEGER,
       allowNull: false
   }
});

Το μοντέλο Grade περιέχει τη στήλη grade.

Για να δείξετε τις συσχετίσεις, θα χρειαστεί να προσθέσετε δείγματα δεδομένων στη βάση δεδομένων. Για αυτό, θα χρησιμοποιήσετε τη μέθοδο bulk(). Αντί να εισάγετε τα δεδομένα στις γραμμές μία-μία, η μέθοδος bulkCreate() σας επιτρέπει να εισάγετε πολλές γραμμές στα μοντέλα της βάσης δεδομένων σας ταυτόχρονα.

Τώρα, εισάγετε τα δεδομένα Grade και Student στα αντίστοιχα μοντέλα τους στη βάση δεδομένων όπως φαίνεται:

...
const grade_data = [{grade : 9}, {grade : 10}, {grade : 11}]

const student_data = [
   {name : "John Baker", gradeId: 2},
   {name : "Max Butler", gradeId: 1},
   {name : "Ryan Fisher", gradeId: 3},
   {name : "Robert Gray", gradeId: 2},
   {name : "Sam Lewis", gradeId: 1}
]

sequelize.sync({ force: true }).then(() => {
   Grade.bulkCreate(grade_data, { validate: true }).then(() => {
       Student.bulkCreate(student_data, { validate: true }).then(() => {
           …
       }).catch((err) => { console.log(err); });
   }).catch((err) => { console.log(err); });
}).catch((error) => {
   console.error('Unable to create the table : ', error);
});

Εδώ, παρέχετε δείγματα δεδομένων και εισάγετε τα δεδομένα στα μοντέλα Student και Grade. Με τη βάση δεδομένων σας, τα μοντέλα και τα δείγματα δεδομένων στη θέση τους, είστε έτοιμοι να δημιουργήσετε συσχετίσεις.

Στο one-to-one.js, προσθέστε την ακόλουθη γραμμή κάτω από το μπλοκ student_data:

...
Student.belongsTo(Grade);

Στη συνέχεια, θα χρειαστεί να ελέγξετε αν η συσχέτιση λειτουργεί σωστά. Για να το κάνετε αυτό, μπορείτε να ανακτήσετε όλα τα δεδομένα των φοιτητών μαζί με τα αντίστοιχα επίπεδα τάξης τους, περνώντας την παράμετρο include μέσα στη μέθοδο findAll().

Δεδομένου ότι χρειάζεται να αποκτήσετε το επίπεδο τάξης του μαθητή, θα περάσετε το Grade ως το μοντέλο. Στη μέθοδο sequelize.sync(), προσθέστε τις επισημασμένες γραμμές όπως φαίνεται:

...
sequelize.sync({ force: true }).then(() => {
   Grade.bulkCreate(grade_data, { validate: true }).then(() => {
       Student.bulkCreate(student_data, { validate: true }).then(() => {
           Student.findAll({
               include: [{
                   model: Grade
               }]
           }).then(result => {
               console.log(result)
           }).catch((error) => {
               console.error('Failed to retrieve data : ', error);
           });
       }).catch((err) => { console.log(err); });
   }).catch((err) => { console.log(err); });
}).catch((error) => {
   console.error('Unable to create the table : ', error);
});

Ο πλήρης κώδικας φαίνεται ως εξής:

const {Sequelize, DataTypes} = require("sequelize");

const sequelize = new Sequelize(
   'student_db',
   'DATABASE_USERNAME',
   'DATABASE_PASSWORD',
    {
      host: 'DATABASE_HOST',
      dialect: 'mysql'
    }
  );
sequelize.authenticate().then(() => {
   console.log('Connection has been established successfully.');
}).catch((error) => {
   console.error('Unable to connect to the database: ', error);
});

const Student = sequelize.define("students", {
   student_id: {
       type: DataTypes.UUID,
       defaultValue: DataTypes.UUIDV4,
       primaryKey: true,
   },
   name: {
       type: DataTypes.STRING,
       allowNull: false
   }
});

const Grade = sequelize.define("grades", {
   grade: {
       type: DataTypes.INTEGER,
       allowNull: false
   }
});

const grade_data = [{grade : 9}, {grade : 10}, {grade : 11}]

const student_data = [
   {name : "John Baker", gradeId: 2},
   {name : "Max Butler", gradeId: 1},
   {name : "Ryan Fisher", gradeId: 3},
   {name : "Robert Gray", gradeId: 2},
   {name : "Sam Lewis", gradeId: 1}
]

// One-To-One association
Student.belongsTo(Grade);

sequelize.sync({ force: true }).then(() => {
   Grade.bulkCreate(grade_data, { validate: true }).then(() => {
       Student.bulkCreate(student_data, { validate: true }).then(() => {
           Student.findAll({
               include: [{
                   model: Grade
               }]
           }).then(result => {
               console.log(result)
           }).catch((error) => {
               console.error('Failed to retrieve data : ', error);
           });
       }).catch((err) => { console.log(err); });
   }).catch((err) => { console.log(err); });
}).catch((error) => {
   console.error('Unable to create the table : ', error);
});

Αποθήκευσε και κλείσε το αρχείο σου.

Τρέξτε το αρχείο χρησιμοποιώντας την ακόλουθη εντολή:

node one_to_one.js

Η έξοδος θα είναι μεγάλη και θα δείτε τα δεδομένα όλων των μαθητών με τα επίπεδα βαθμολογίας τους. Ακολουθεί ένα απόσπασμα της εξόδου που δείχνει τα δεδομένα των μαθητών:

students {
    dataValues:
   { student_id: '3e786a8f-7f27-4c59-8e9c-a8c606892288',
       name: 'Sam Lewis',
       createdAt: 2021-12-16T08:49:38.000Z,
       updatedAt: 2021-12-16T08:49:38.000Z,
       gradeId: 1,
       grade: [grades] },
    _previousDataValues:
...

Ανάλογα με τα εργαλεία γραμμής εντολών που χρησιμοποιείτε, η έξοδος μπορεί να εμφανίζεται σε εκτεταμένη προβολή ή όχι. Αν είναι σε εκτεταμένη προβολή, εμφανίζει το εκτεταμένο αντικείμενο grade ως έξοδο.

Σε αυτήν την ενότητα, δημιουργήσατε μια σχέση ένα προς ένα χρησιμοποιώντας την κλήση μεθόδου Student.belongsTo(Grade); και λάβατε τις λεπτομέρειες σύμφωνα με τη συσχέτιση που δημιουργήσατε.

Δημιουργία Σχέσης Ένα προς Πολλά με hasMany()

Σε αυτή την ενότητα, θα δημιουργήσετε μια σχέση ένα-προς-πολλά χρησιμοποιώντας μοντέλα Sequelize. Φανταστείτε ότι θέλετε να πάρετε όλους τους μαθητές που σχετίζονται με ένα επιλεγμένο επίπεδο τάξης. Δεδομένου ότι ένα συγκεκριμένο επίπεδο τάξης μπορεί να έχει πολλούς μαθητές, πρόκειται για μια σχέση ένα-προς-πολλά.

Για να ξεκινήσετε, αντιγράψτε τα περιεχόμενα του one_to_one.js σε ένα νέο αρχείο με το όνομα one_to_many.js. Στο one_to_many.js, αφαιρέστε τις γραμμές μετά το block student_data. Το αρχείο one_to_many.js σας θα μοιάζει με αυτό:

const {Sequelize, DataTypes} = require("sequelize");

const sequelize = new Sequelize(
   'student_db',
   'DATABASE_USERNAME',
   'DATABASE_PASSWORD',
    {
      host: 'DATABASE_HOST',
      dialect: 'mysql'
    }
  );

sequelize.authenticate().then(() => {
   console.log('Connection has been established successfully.');
}).catch((error) => {
   console.error('Unable to connect to the database: ', error);
});

const Student = sequelize.define("students", {
   student_id: {
       type: DataTypes.UUID,
       defaultValue: DataTypes.UUIDV4,
       primaryKey: true,
   },
   name: {
       type: DataTypes.STRING,
       allowNull: false
   }
});
const Grade = sequelize.define("grades", {
   grade: {
       type: DataTypes.INTEGER,
       allowNull: false
   }
});

const grade_data = [ {grade : 9}, {grade : 10}, {grade : 11}]

const student_data = [
   {name : "John Baker", gradeId: 2},
   {name : "Max Butler", gradeId: 1},
   {name : "Ryan Fisher", gradeId: 3},
   {name : "Robert Gray", gradeId: 2},
   {name : "Sam Lewis", gradeId: 1}
]

Μετά το μπλοκ student_data, χρησιμοποιήστε τη μέθοδο hasMany() για να δημιουργήσετε μια νέα σχέση:

...
Grade.hasMany(Student)

Η μέθοδος hasMany() σας επιτρέπει να δημιουργήσετε μια σχέση ένα-προς-πολλά μεταξύ δύο μοντέλων Sequelize. Εδώ, χρησιμοποιείτε τα μοντέλα Grade και Student.

Στη συνέχεια, προσθέστε τη μέθοδο sequelize.sync() μαζί με τη μέθοδο findAll() κάτω από τη γραμμή hasMany():

...
sequelize.sync({ force: true }).then(() => {
   Grade.bulkCreate(grade_data, { validate: true }).then(() => {
       Student.bulkCreate(student_data, { validate: true }).then(() => {
           Grade.findAll({
               where: {
                   grade: 9
               },
               include: [{
                   model: Student
               }]
           }).then(result => {
               console.dir(result, { depth: 5 });
           }).catch((error) => {
               console.error('Failed to retrieve data : ', error);
           });
       }).catch((err) => { console.log(err); });
   }).catch((err) => { console.log(err); });
}).catch((error) => {
   console.error('Unable to create table : ', error);
});

Εδώ προσπαθείτε να αποκτήσετε πρόσβαση σε όλους τους μαθητές σε ένα συγκεκριμένο επίπεδο τάξης—σε αυτή την περίπτωση, σε όλους τους μαθητές της τάξης 9. Επιπλέον, προσθέσατε το μοντέλο Student στην επιλογή include.

Εδώ είναι ο πλήρης κώδικας:

const {Sequelize, DataTypes} = require("sequelize");

const sequelize = new Sequelize(
   'student_db',
   'DATABASE_USERNAME',
   'DATABASE_PASSWORD',
    {
      host: 'DATABASE_HOST',
      dialect: 'mysql'
    }
  );

sequelize.authenticate().then(() => {
   console.log('Connection has been established successfully.');
}).catch((error) => {
   console.error('Unable to connect to the database: ', error);
});

const Student = sequelize.define("students", {
   student_id: {
       type: DataTypes.UUID,
       defaultValue: DataTypes.UUIDV4,
       primaryKey: true,
   },
   name: {
       type: DataTypes.STRING,
       allowNull: false
   }
});
const Grade = sequelize.define("grades", {
   grade: {
       type: DataTypes.INTEGER,
       allowNull: false
   }
});

const grade_data = [ {grade : 9}, {grade : 10}, {grade : 11}]

const student_data = [
   {name : "John Baker", gradeId: 2},
   {name : "Max Butler", gradeId: 1},
   {name : "Ryan Fisher", gradeId: 3},
   {name : "Robert Gray", gradeId: 2},
   {name : "Sam Lewis", gradeId: 1}
]

// One-To-Many relationship
Grade.hasMany(Student);

sequelize.sync({ force: true }).then(() => {
   Grade.bulkCreate(grade_data, { validate: true }).then(() => {
       Student.bulkCreate(student_data, { validate: true }).then(() => {
           Grade.findAll({
               where: {
                   grade: 9
               },
               include: [{
                   model: Student
               }]
           }).then(result => {
               console.dir(result, { depth: 5 });
           }).catch((error) => {
               console.error('Failed to retrieve data : ', error);
           });
       }).catch((err) => { console.log(err); });
   }).catch((err) => { console.log(err); });
}).catch((error) => {
   console.error('Unable to create table : ', error);
});

Αποθήκευσε και κλείσε το αρχείο σου.

Τρέξτε το αρχείο με την ακόλουθη εντολή:

node one_to_many.js

Η έξοδος θα μοιάζει με την ακόλουθη. Θα είναι αρκετά μεγάλη, αλλά όλοι οι μαθητές της τάξης 9 θα επιστραφούν ως εξής:

[ grades {
    dataValues:
     { id: 1,
       grade: 9,
       createdAt: 2021-12-20T05:12:31.000Z,
       updatedAt: 2021-12-20T05:12:31.000Z,
       students:
        [ students {
            dataValues:
             { student_id: '8a648756-4e22-4bc0-8227-f590335f9965',
               name: 'Sam Lewis',
               createdAt: 2021-12-20T05:12:31.000Z,
               updatedAt: 2021-12-20T05:12:31.000Z,
               gradeId: 1 },
...
          students {
            dataValues:
             { student_id: 'f0304585-91e5-4efc-bdca-501b3dc77ee5',
               name: 'Max Butler',
               createdAt: 2021-12-20T05:12:31.000Z,
               updatedAt: 2021-12-20T05:12:31.000Z,
               gradeId: 1 },
...

Σε αυτήν την ενότητα, δημιουργήσατε μια σχέση ένα προς πολλά χρησιμοποιώντας την κλήση μεθόδου Grade.hasMany(Student);. Στην έξοδο, ανακτήσατε τις λεπτομέρειες σύμφωνα με τη συσχέτιση που δημιουργήσατε.

Δημιουργία Σχέσεων Πολλών-Προς-Πολλούς με belongsToMany()

Σε αυτήν την ενότητα, θα δημιουργήσετε σχέσεις πολλών προς πολλούς χρησιμοποιώντας τα μοντέλα του Sequelize. Για παράδειγμα, φανταστείτε μια κατάσταση όπου οι φοιτητές είναι εγγεγραμμένοι σε μαθήματα. Ένας φοιτητής μπορεί να εγγραφεί σε πολλά μαθήματα και ένα μάθημα μπορεί να έχει πολλούς φοιτητές. Αυτή είναι μια σχέση πολλών προς πολλούς. Για να την υλοποιήσετε χρησιμοποιώντας το Sequelize, θα χρησιμοποιήσετε τα μοντέλα Student, Course, και StudentCourse με τη μέθοδο belongsToMany().

Για να ξεκινήσετε, δημιουργήστε ένα αρχείο με το όνομα many_to_many.js και προσθέστε τα μπλοκ κώδικα για την αρχικοποίηση και την αυθεντικοποίηση της βάσης δεδομένων όπως παρακάτω. (Μπορείτε να ξαναχρησιμοποιήσετε τα μπλοκ κώδικα από το προηγούμενο παράδειγμα one_to_many.js.) Βεβαιωθείτε ότι έχετε ενημερώσει τις επισημασμένες τιμές σύνδεσης της βάσης δεδομένων όπως χρειάζεται.

const {Sequelize, DataTypes} = require("sequelize");

const sequelize = new Sequelize(
   'student_db',
   'DATABASE_USERNAME',
   'DATABASE_PASSWORD',
    {
      host: 'DATABASE_HOST',
      dialect: 'mysql'
    }
);

sequelize.authenticate().then(() => {
    console.log('Connection has been established successfully.');
}).catch((error) => {
    console.error('Unable to connect to the database: ', error);
});

Στη συνέχεια, θα δημιουργήσετε τα μοντέλα βάσης δεδομένων για σχέσεις πολλών προς πολλούς: Student και Course. Έπειτα, θα προσθέσετε κάποια δείγματα δεδομένων σε αυτά τα μοντέλα.

...

const Student = sequelize.define("students", {
    student_id: {
        type: DataTypes.UUID,
        defaultValue: DataTypes.UUIDV4,
    },
    name: {
        type: DataTypes.STRING,
        allowNull: false
    }
});

const Course = sequelize.define("courses", {
    course_name: {
        type: DataTypes.STRING,
        allowNull: false
    }
});

const StudentCourse = sequelize.define('StudentCourse', {
    id: {
      type: DataTypes.INTEGER,
      primaryKey: true,
      autoIncrement: true,
      allowNull: false
    }
  });

const course_data = [
    {course_name : "Science"},
    {course_name : "Maths"},
    {course_name : "History"}
]

const student_data = [
    {name : "John Baker", courseId: 2},
    {name : "Max Butler", courseId: 1},
    {name : "Ryan Fisher", courseId: 3},
    {name : "Robert Gray", courseId: 2},
    {name : "Sam Lewis", courseId: 1}
]

const student_course_data = [
    {studentId : 1, courseId: 1},
    {studentId : 2, courseId: 1},
    {studentId : 2, courseId: 3},
    {studentId : 3, courseId: 2},
    {studentId : 1, courseId: 2},
]

Εδώ, δημιουργείτε τα μοντέλα Student και Course και παρέχετε μερικά δείγματα δεδομένων. Επίσης, ορίζετε ένα courseID, το οποίο θα χρησιμοποιήσετε για να ανακτήσετε τους φοιτητές σύμφωνα με αυτόν τον τύπο σχέσης.

Τέλος, ορίσατε ένα νέο μοντέλο που ονομάζεται StudentCourse, το οποίο διαχειρίζεται τα δεδομένα σχέσης μεταξύ Student και Course. Σε αυτό το παράδειγμα, ο studentId 1 είναι εγγεγραμμένος στο courseId 1 και στο courseId 2.

Έχετε ολοκληρώσει την αρχικοποίηση της βάσης δεδομένων και έχετε προσθέσει δείγματα δεδομένων στη βάση δεδομένων. Στη συνέχεια, δημιουργήστε σχέσεις πολλών προς πολλούς χρησιμοποιώντας τη μέθοδο belongsToMany() όπως φαίνεται:

...
Course.belongsToMany(Student, { through: 'StudentCourse'})
Student.belongsToMany(Course, { through: 'StudentCourse'})

Μέσα στη μέθοδο belongsToMany(), περνάτε τη ρύθμιση through με το όνομα του μοντέλου ως επιλογή ρύθμισης. Σε αυτή την περίπτωση, είναι StudentCourse. Αυτός είναι ο πίνακας που διαχειρίζεται τις σχέσεις πολλαπλών προς πολλαπλές.

Τέλος, μπορείτε να ελέγξετε αν η σχέση λειτουργεί σωστά ανακτώντας όλα τα δεδομένα των μαθημάτων με τους αντίστοιχους φοιτητές. Θα το κάνετε αυτό χρησιμοποιώντας την παράμετρο include μέσα στη μέθοδο findAll(). Προσθέστε τις ακόλουθες γραμμές στο many_to_many.js:

...
sequelize.sync({ force: true }).then(() => {
    Course.bulkCreate(course_data, { validate: true }).then(() => {
        Student.bulkCreate(student_data, { validate: true }).then(() => {
            StudentCourse.bulkCreate(student_course_data, { validate: true }).then(() => {
                Course.findAll({
                    include: {
                        model: Student,
                    },
                }).then(result => {
                    console.log(result);
                }).catch((error) => {
                    console.error('Failed to retrieve data : ', error);
                });
            }).catch((error) => {
                console.log(error);
            });
        }).catch((error) => {
            console.log(error);
        });
    }).catch((error) => {
        console.log(error);
    });
}).catch((error) => {
    console.error('Unable to create table : ', error);
});

Ο πλήρης κώδικας φαίνεται ως εξής:

const {Sequelize, DataTypes} = require("sequelize");

const sequelize = new Sequelize(
   'student_db',
   'DATABASE_USERNAME',
   'DATABASE_PASSWORD',
    {
      host: 'DATABASE_HOST',
      dialect: 'mysql'
    }
);

sequelize.authenticate().then(() => {
   console.log('Connection has been established successfully.');
}).catch((error) => {
   console.error('Unable to connect to the database: ', error);
});

const Student = sequelize.define("students", {
    student_id: {
       type: DataTypes.UUID,
       defaultValue: DataTypes.UUIDV4,
    },
    name: {
       type: DataTypes.STRING,
       allowNull: false
    }
});

const Course = sequelize.define("courses", {
    course_name: {
        type: DataTypes.STRING,
        allowNull: false
    }
});

const StudentCourse = sequelize.define('StudentCourse', {
    id: {
      type: DataTypes.INTEGER,
      primaryKey: true,
      autoIncrement: true,
      allowNull: false
    }
  });

const course_data = [
    {course_name : "Science"},
    {course_name : "Maths"},
    {course_name : "History"}
]

const student_data = [
    {name : "John Baker", courseId: 2},
    {name : "Max Butler", courseId: 1},
    {name : "Ryan Fisher", courseId: 3},
    {name : "Robert Gray", courseId: 2},
    {name : "Sam Lewis", courseId: 1}
]

const student_course_data = [
    {studentId : 1, courseId: 1},
    {studentId : 2, courseId: 1},
    {studentId : 2, courseId: 3},
    {studentId : 3, courseId: 2},
    {studentId : 1, courseId: 2},
]

Course.belongsToMany(Student, { through: 'StudentCourse'})
Student.belongsToMany(Course, { through: 'StudentCourse'})

sequelize.sync({ force: true }).then(() => {
    Course.bulkCreate(course_data, { validate: true }).then(() => {
        Student.bulkCreate(student_data, { validate: true }).then(() => {
            StudentCourse.bulkCreate(student_course_data, { validate: true }).then(() => {
                Course.findAll({
                    include: {
                        model: Student,
                    },
                }).then(result => {
                    console.log(result);
                }).catch((error) => {
                    console.error('Failed to retrieve data : ', error);
                });
            }).catch((error) => {
                console.log(error);
            });
        }).catch((error) => {
            console.log(error);
        });
    }).catch((error) => {
        console.log(error);
    });
}).catch((error) => {
    console.error('Unable to create table : ', error);
});

Αποθήκευσε και κλείσε το αρχείο.

Τρέξτε το αρχείο χρησιμοποιώντας την ακόλουθη εντολή:

node many_to_many.js

Η έξοδος θα είναι μεγάλη, αλλά θα μοιάζει κάπως με την εξής:

[ courses {
    dataValues:
     { id: 1,
       course_name: 'Science',
       createdAt: 2022-05-11T04:27:37.000Z,
       updatedAt: 2022-05-11T04:27:37.000Z,
       students: [Array] },
    _previousDataValues:
     { id: 1,
       course_name: 'Science',
       createdAt: 2022-05-11T04:27:37.000Z,
       updatedAt: 2022-05-11T04:27:37.000Z,
       students: [Array] },
    _changed: Set {},
    _options:
     { isNewRecord: false,
       _schema: null,
       _schemaDelimiter: '',
       include: [Array],
       includeNames: [Array],
       includeMap: [Object],
       includeValidated: true,
       attributes: [Array],
       raw: true },
    isNewRecord: false,
    students: [ [students], [students] ] },
  courses {
    dataValues:
     { id: 2,
       course_name: 'Maths',
       createdAt: 2022-05-11T04:27:37.000Z,
       updatedAt: 2022-05-11T04:27:37.000Z,
       students: [Array] },
    _previousDataValues:
...

Όπως μπορείτε να δείτε σε αυτή την έξοδο, ανακτήθηκαν τα μαθήματα με τους συνδεδεμένους φοιτητές. Μέσα στο μπλοκ courses, θα δείτε ξεχωριστές τιμές id που υποδεικνύουν κάθε μάθημα. Για παράδειγμα, το id: 1 συνδέεται με το course_name: Science για το μάθημα της Επιστήμης, ενώ το id: 2 είναι το μάθημα των Μαθηματικών, και ούτω καθεξής.

Στη βάση δεδομένων, μπορείτε να δείτε τους τρεις δημιουργημένους πίνακες με τα δείγματα δεδομένων που εισαγάγατε.

Σε αυτό το βήμα, χρησιμοποιήσατε το Sequelize για να δημιουργήσετε σχέσεις ένα προς ένα, ένα προς πολλά και πολλά προς πολλά. Στη συνέχεια, θα δουλέψετε με ακατέργαστα ερωτήματα.

Εργασία με Ακατέργαστα Ερωτήματα

Σε αυτό το βήμα, θα εργαστείτε με ακατέργαστα ερωτήματα στο Sequelize. Στα προηγούμενα βήματα, χρησιμοποιήσατε ενσωματωμένες μεθόδους του Sequelize, όπως insert() και findAll(), για την εισαγωγή και την επιλογή δεδομένων από τη βάση δεδομένων. Ίσως να έχετε παρατηρήσει ότι αυτές οι μέθοδοι ακολουθούν ένα συγκεκριμένο πρότυπο για τη συγγραφή ενός ερωτήματος. Ωστόσο, χρησιμοποιώντας ακατέργαστα ερωτήματα, δεν χρειάζεται να ανησυχείτε για τις ενσωματωμένες μεθόδους και τα πρότυπα του Sequelize. Χρησιμοποιώντας τις γνώσεις σας στα ερωτήματα SQL, μπορείτε να εκτελέσετε μια ποικιλία ερωτημάτων στο Sequelize, από τα απλά έως τα πιο προχωρημένα.

Εδώ είναι ένα παράδειγμα ακατέργαστων ερωτημάτων που εκτελούν την ενέργεια επιλογής όλων των τιμών από έναν συγκεκριμένο πίνακα, διαγράφοντας τις επιλεγμένες τιμές σύμφωνα με την προϋπόθεση και ενημερώνοντας τον πίνακα με τις δοθείσες τιμές.

SELECT * FROM table_name;
DELETE FROM table_name WHERE condition;
UPDATE table_name SET y = 42 WHERE x = 12;

Στο Sequelize, οι ακατέργαστες ερωτήσεις μπορούν να χρησιμοποιηθούν κυρίως με δύο μεθοδολογίες: αντικατάσταση με πίνακα και αντικατάσταση με αντικείμενο. Όταν περνάτε τιμές στην ερώτηση SQL, μπορείτε να χρησιμοποιήσετε είτε έναν πίνακα είτε ένα αντικείμενο για να πραγματοποιήσετε αυτήν την αντικατάσταση.

Πριν γράψετε ένα ακατέργαστο ερώτημα, θα χρειαστεί πρώτα να παρέχετε δεδομένα μαθητών σε μια δείγματική βάση δεδομένων. Ακολουθώντας την προηγούμενη ενότητα, Δημιουργία Δείγματος Βάσης Δεδομένων, συνδεθείτε στο MySQL, δημιουργήστε μια βάση δεδομένων με το όνομα sample_student_db και αποσυνδεθείτε από το MySQL.

Στη συνέχεια, θα προσθέσετε μερικά ακατέργαστα δεδομένα για να ξεκινήσετε να εργάζεστε με ακατέργαστες ερωτήσεις. Δημιουργήστε ένα νέο αρχείο με όνομα add_student_records.js και προσθέστε τα ακόλουθα μπλοκ κώδικα, τα οποία περιέχουν τις μεθόδους του Sequelize που συζητήθηκαν προηγουμένως, authenticate(), sync() και bulkCreate().

const {Sequelize, DataTypes} = require("sequelize");

const sequelize = new Sequelize(
   'sample_student_db',
   'DATABASE_USERNAME',
   'DATABASE_PASSWORD',
    {
      host: 'DATABASE_HOST',
      dialect: 'mysql'
    }
   );

sequelize.authenticate().then(() => {
    console.log('Connection has been established successfully.');
}).catch((error) => {
    console.error('Unable to connect to the database: ', error);
});

const Student = sequelize.define("students", {
    student_id: {
        type: DataTypes.UUID,
        defaultValue: DataTypes.UUIDV4,
        primaryKey: true,
    },
    name: {
        type: DataTypes.STRING,
        allowNull: false
    }
});

const student_data = [
    {name : "John Baker"},
    {name : "Max Butler"},
    {name : "Ryan Fisher"},
    {name : "Robert Gray"},
    {name : "Sam Lewis"}
]

sequelize.sync({ force: true }).then(() => {

    Student.bulkCreate(student_data, { validate: true }).then((result) => {
        console.log(result);
    }).catch((error) => {
        console.log(error);
    });

}).catch((error) => {
    console.error('Unable to create table : ', error);
});

Εδώ, ξεκινάτε τη σύνδεση με τη βάση δεδομένων, δημιουργείτε το μοντέλο και εισάγετε μερικές εγγραφές μαθητών στη νέα βάση δεδομένων.

Αποθήκευσε και κλείσε το αρχείο.

Στη συνέχεια, εκτελέστε αυτό το σενάριο χρησιμοποιώντας την ακόλουθη εντολή:

node add_student_records.js

Η έξοδος θα είναι κάτι παρόμοιο με το ακόλουθο. Θα είναι αρκετά μεγάλη, αλλά όλα τα αρχεία των φοιτητών που εισαγάγατε θα επιστραφούν ως εξής. Σημειώστε ότι, αφού το student_id είναι μια αυτόματα δημιουργούμενη τιμή UUID (Παγκόσμια Μοναδικοί Αναγνωριστές), θα είναι διαφορετική ανάλογα με τον χρήστη.

Executing (default): SELECT 1+1 AS result
Executing (default): DROP TABLE IF EXISTS `students`;
Connection has been established successfully.
Executing (default): DROP TABLE IF EXISTS `students`;
Executing (default): CREATE TABLE IF NOT EXISTS `students` (`student_id` CHAR(36) BINARY , `name` VARCHAR(255) NOT NULL, `createdAt` DATETIME NOT NULL, `updatedAt` DATETIME NOT NULL, PRIMARY KEY (`student_id`)) ENGINE=InnoDB;
Executing (default): SHOW INDEX FROM `students`
Executing (default): INSERT INTO `students` (`student_id`,`name`,`createdAt`,`updatedAt`) VALUES ('45d1f26c-ba76-431f-ac5f-f41282351710','John Baker','2022-06-03 07:27:49','2022-06-03 07:27:49'),('1cb4e34d-bfcf-4a97-9624-e400b9a1a5f2','Max Butler','2022-06-03 07:27:49','2022-06-03 07:27:49'),('954c576b-ba1c-4dbc-a5c6-8eaf22bbbb04','Ryan Fisher','2022-06-03 07:27:49','2022-06-03 07:27:49'),('e0f15cd3-0025-4032-bfe8-774e38e14c5f','Robert Gray','2022-06-03 07:27:49','2022-06-03 07:27:49'),('826a0ec9-edd0-443f-bb12-068235806659','Sam Lewis','2022-06-03 07:27:49','2022-06-03 07:27:49');
[
  students {
    dataValues: {
      student_id: '45d1f26c-ba76-431f-ac5f-f41282351710',
      name: 'John Baker',
      createdAt: 2022-06-03T07:27:49.453Z,
      updatedAt: 2022-06-03T07:27:49.453Z
    },
    _previousDataValues: {
      name: 'John Baker',
      student_id: '45d1f26c-ba76-431f-ac5f-f41282351710',
      createdAt: 2022-06-03T07:27:49.453Z,
      updatedAt: 2022-06-03T07:27:49.453Z
    },

…

Στην επόμενη ενότητα, θα εφαρμόσετε ακατέργαστα ερωτήματα χρησιμοποιώντας ένα από τα αποτελέσματα student_id στο μπλοκ κώδικα παραπάνω. Αντιγράψτε το ώστε να το έχετε για τις επόμενες ενότητες, όπου θα χρησιμοποιήσετε τη μέθοδο query() για αντικαταστάσεις σε πίνακες και αντικείμενα.

Αντικατάσταση Πίνακα

Σε αυτή την ενότητα, θα χρησιμοποιήσετε τη μέθοδο query() για αντικατάσταση πίνακα. Με αυτή τη μέθοδο, το Sequelize μπορεί να εκτελεί ακατέργαστα ή ήδη προετοιμασμένα ερωτήματα SQL.

Για να ξεκινήσετε, αντιγράψτε τα περιεχόμενα του αρχείου server.js από το Βήμα 1, καθώς περιλαμβάνει τη μέθοδο εκκίνησης Sequelize() και την έναρξη της βάσης δεδομένων. Επικολλήστε τα περιεχόμενα σε ένα νέο αρχείο με όνομα array_raw_query.js. Ενημερώστε το όνομα της βάσης δεδομένων σε sample_student_db:

const {Sequelize, DataTypes} = require("sequelize");

const sequelize = new Sequelize(
   'sample_student_db',
   'DATABASE_USERNAME',
   'DATABASE_PASSWORD',
    {
      host: 'DATABASE_HOST',
      dialect: 'mysql'
    }
   );

sequelize.authenticate().then(() => {
    console.log('Connection has been established successfully.');
}).catch((error) => {
    console.error('Unable to connect to the database: ', error);
});

Στο τέλος του αρχείου, προσθέστε το ακόλουθο μπλοκ κώδικα για αντικατάσταση πίνακα, φροντίζοντας να αντικαταστήσετε το REPLACE_STUDENT_ID με την τιμή student_id που αντιγράψατε στην προηγούμενη ενότητα.

...
sequelize.query(
    'SELECT * FROM students WHERE student_id = ?',
    {
      replacements: ['REPLACE_STUDENT_ID'],
      type: sequelize.QueryTypes.SELECT
    }
).then(result => {
    console.log(result);
}).catch((error) => {
    console.error('Failed to insert data : ', error);
});

Για αντικατάσταση σε πίνακες, περνάτε τη μέθοδο query() με το ερώτημα SQL και το αντικείμενο ρυθμίσεων. Περιέχει την τιμή και τον τύπο replacements. Στις αντικαταστάσεις, περνάτε δεδομένα ως πίνακα και λαμβάνετε αυτές τις τιμές χρησιμοποιώντας το σύμβολο ερωτηματικού (?).

Στη συνέχεια, αφού χρειάζεται να αποκτήσετε δεδομένα για έναν συγκεκριμένο μαθητή, το student_id περνάει ως δεύτερη παράμετρος. Μετά από αυτό, περνάτε το ζεύγος κλειδί-τιμή type: sequelize.QueryTypes.SELECT, το οποίο μπορείτε να χρησιμοποιήσετε για να επιλέξετε δεδομένα από τη βάση δεδομένων.

Υπάρχουν και κάποιες άλλες κατηγορίες, όπως QueryTypes.UPDATE και QueryTypes.DELETE. Ανάλογα με την απαίτηση, μπορείτε να επιλέξετε τον τύπο που ταιριάζει στον σκοπό σας.

Το παρακάτω δείχνει ολόκληρο το μπλοκ κώδικα. Εδώ συνδέεστε με τη βάση δεδομένων και ανακτάτε τα επιλεγμένα δεδομένα του μαθητή χρησιμοποιώντας μια απλή ερώτηση (raw query).

const {Sequelize, DataTypes} = require("sequelize");

const sequelize = new Sequelize(
   'sample_student_db',
   'DATABASE_USERNAME',
   'DATABASE_PASSWORD',
    {
      host: 'DATABASE_HOST',
      dialect: 'mysql'
    }
   );

sequelize.authenticate().then(() => {
    console.log('Connection has been established successfully.');
}).catch((error) => {
    console.error('Unable to connect to the database: ', error);
});

sequelize.query(
    'SELECT * FROM students WHERE student_id = ?',
    {
      replacements: ['REPLACE_STUDENT_ID'],
      type: sequelize.QueryTypes.SELECT
    }
).then(result => {
    console.log(result);
}).catch((error) => {
    console.error('Failed to insert data : ', error);
});

Αποθήκευσε και κλείσε το αρχείο σου.

Στη συνέχεια, μπορείτε να εκτελέσετε αυτό το σενάριο χρησιμοποιώντας την ακόλουθη εντολή:

node array_raw_query.js

Θα δείτε έξοδο παρόμοια με την ακόλουθη:

Connection has been established successfully.
[ { student_id: 'STUDENT_ID_YOU_RETRIEVED',
    name: 'Robert Gray',
    createdAt: 2022-05-06T13:14:50.000Z,
    updatedAt: 2022-05-06T13:14:50.000Z } ]

Λόγω του επιλεγμένου student_id, οι τιμές εξόδου σας ενδέχεται να διαφέρουν.

Αντικατάσταση Αντικειμένου

Στην επιφάνεια, η αντικατάσταση αντικειμένων μοιάζει με την αντικατάσταση πίνακα, αλλά το μοτίβο για τη μεταβίβαση δεδομένων στο ακατέργαστο ερώτημα είναι διαφορετικό. Στην επιλογή αντικατάστασης, περνάτε δεδομένα ως αντικείμενο, ενώ στην επιλογή ερωτήματος, χρησιμοποιείτε τιμές όπως :key.

Για να ξεκινήσετε, δημιουργήστε ένα νέο αρχείο με το όνομα object_raw_query.js και επικολλήστε τα πλήρη μπλοκ κώδικα από το αρχείο server.js, ενημερώνοντας τη βάση δεδομένων σε sample_student_db.

const {Sequelize, DataTypes} = require("sequelize");

const sequelize = new Sequelize(
   'sample_student_db',
   'DATABASE_USERNAME',
   'DATABASE_PASSWORD',
    {
      host: 'DATABASE_HOST',
      dialect: 'mysql'
    }
   );

sequelize.authenticate().then(() => {
    console.log('Connection has been established successfully.');
}).catch((error) => {
    console.error('Unable to connect to the database: ', error);
});

Στη συνέχεια, προσθέστε το ακόλουθο μπλοκ κώδικα στο τέλος του νέου αρχείου object_raw_query.js:

...
sequelize.query(
  'SELECT * FROM students WHERE student_id = :id',
  {
    replacements: { id: 'REPLACE_STUDENT_ID' },
    type: sequelize.QueryTypes.SELECT
  }
 ).then(result => {
    console.log(result);
}).catch((error) => {
    console.error('Failed to insert data : ', error);
});

Εδώ, λαμβάνετε τα δεδομένα του επιλεγμένου μαθητή χρησιμοποιώντας τη μέθοδο αντικατάστασης αντικειμένου. Δημιουργείτε ένα αντικείμενο replacement, ορίζοντας το id ως τις πληροφορίες του μαθητή που θέλετε να ανακτήσετε: { id: '<mark>REPLACE_STUDENT_ID</mark>' }.

Στη μέθοδο query(), υποδεικνύετε: 'SELECT * FROM students WHERE student_id=:id'. Χρησιμοποιώντας τη μέθοδο query(), περνάτε την τιμή αντικατάστασης ως αντικείμενο, γι' αυτό αυτή η μέθοδος είναι γνωστή ως αντικατάσταση αντικειμένου.

Εδώ είναι ο πλήρης κώδικας:

const {Sequelize, DataTypes} = require("sequelize");

const sequelize = new Sequelize(
   'sample_student_db',
   'DATABASE_USERNAME',
   'DATABASE_PASSWORD',
    {
      host: 'DATABASE_HOST',
      dialect: 'mysql'
    }
   );

sequelize.authenticate().then(() => {
    console.log('Connection has been established successfully.');
}).catch((error) => {
    console.error('Unable to connect to the database: ', error);
});

sequelize.query(
  'SELECT * FROM students WHERE student_id = :id',
  {
    replacements: { id: 'REPLACE_STUDENT_ID' },
    type: sequelize.QueryTypes.SELECT
  }
 ).then(result => {
    console.log(result);
}).catch((error) => {
    console.error('Failed to insert data : ', error);
});

Αποθήκευσε και κλείσε το αρχείο.

Στη συνέχεια, εκτελέστε αυτό το σενάριο χρησιμοποιώντας την ακόλουθη εντολή:

node object_raw_query.js

Η έξοδος θα μοιάζει με την ακόλουθη:

Connection has been established successfully.
[ { student_id: 'STUDENT_ID_YOU_RETRIEVED',
    name: 'Robert Gray',
    createdAt: 2022-05-06T13:14:50.000Z,
    updatedAt: 2022-05-06T13:14:50.000Z } ]

Λόγω του επιλεγμένου student_id, οι τιμές εξόδου σας ενδέχεται να διαφέρουν.

Σε αυτό το βήμα, εργάστηκες με πρώτες ερωτήσεις (raw queries) του Sequelize χρησιμοποιώντας δύο διαφορετικές μεθοδολογίες: αντικατάσταση πίνακα και αντικατάσταση αντικειμένου.

Διαμόρφωση μεταβλητών περιβάλλοντος για ασφαλείς συνδέσεις βάσης δεδομένων

Μέχρι αυτό το σημείο, έχετε αποθηκεύσει τα διαπιστευτήρια της βάσης δεδομένων απευθείας στον κώδικά σας. Αν και αυτή η προσέγγιση λειτουργεί για τοπικά πειράματα, δεν είναι ασφαλής. Η σκληρή κωδικοποίηση των διαπιστευτηρίων εκθέτει ευαίσθητες πληροφορίες όπως τους κωδικούς πρόσβασης και τα ονόματα κεντρικών υπολογιστών της βάσης δεδομένων, και αυξάνει τον κίνδυνο παραβιάσεων όταν ο κώδικας κοινοποιείται ή αναπτύσσεται. Σε αυτή την ενότητα, θα μάθετε πώς να αποθηκεύετε αυτά τα διαπιστευτήρια με ασφάλεια χρησιμοποιώντας μεταβλητές περιβάλλοντος.

Γιατί να χρησιμοποιούμε μεταβλητές περιβάλλοντος;

Οι μεταβλητές περιβάλλοντος λειτουργούν ως εξωτερικές παράμετροι ρύθμισης που η εφαρμογή σας μπορεί να διαβάσει κατά την εκτέλεση. Αντί να ενσωματώνονται τα διαπιστευτήρια απευθείας στον κώδικά σας, αποθηκεύονται στο σύστημά σας ή σε ένα ξεχωριστό αρχείο ρύθμισης που δεν υποβάλλεται ποτέ σε έλεγχο εκδόσεων. Αυτή η προσέγγιση προσφέρει πολλαπλά οφέλη:

  • Ασφάλεια: Τα διαπιστευτήριά σας παραμένουν κρυμμένα από δημόσια αποθετήρια και συστήματα ελέγχου εκδόσεων.
  • Ευελιξία: Κάθε περιβάλλον (ανάπτυξης, δοκιμών, παραγωγής) μπορεί να χρησιμοποιεί διαφορετική διαμόρφωση βάσης δεδομένων χωρίς να τροποποιείται ο πηγαίος κώδικας.
  • Δυνατότητα συντήρησης: Η κεντρική διαχείριση ρυθμίσεων επιτρέπει εύκολες ενημερώσεις· εάν αλλάξει ο κωδικός της βάσης δεδομένων, χρειάζεται να τροποποιήσετε μόνο ένα αρχείο ή μια μεταβλητή.
  • Συμμόρφωση: Αυτή η πρακτική ευθυγραμμίζεται με τη μεθοδολογία Twelve-Factor App, η οποία προωθεί τη διαχείριση διαμορφώσεων ανά περιβάλλον για εφαρμογές που μπορούν να κλιμακωθούν.

Ρύθμιση μεταβλητών περιβάλλοντος

Θα χρησιμοποιήσετε το πακέτο dotenv για να διαχειριστείτε τις μεταβλητές περιβάλλοντος σας στο Node.js. Αυτή η βιβλιοθήκη διαβάζει τις μεταβλητές από ένα αρχείο .env και τις εισάγει στο αντικείμενο process.env του Node.js, καθιστώντας τις προσβάσιμες σε ολόκληρη την εφαρμογή σας.

Εγκαταστήστε το πακέτο dotenv εκτελώντας την ακόλουθη εντολή:

npm install dotenv

Μετά την εγκατάσταση, δημιουργήστε ένα νέο αρχείο με όνομα .env στον κεντρικό φάκελο του έργου σας. Αυτό το αρχείο θα περιέχει όλα τα ευαίσθητα δεδομένα που απαιτούνται για τη σύνδεση με τη βάση δεδομένων.

Ακολουθεί ένα παράδειγμα διαμόρφωσης αρχείου .env για τη ρύθμιση του Sequelize σας:

DB_NAME=hello_world_db
DB_USER=your_username
DB_PASSWORD=your_password
DB_HOST=localhost
DB_DIALECT=mysql

Κάθε μεταβλητή αντιστοιχεί σε μια συγκεκριμένη παράμετρο που χρησιμοποιεί το Sequelize για να δημιουργήσει τη σύνδεση.

Ασφάλιση του αρχείου .env

Είναι ζωτικής σημασίας το αρχείο σας .env να μην εμφανίζεται ποτέ στο σύστημα ελέγχου εκδόσεων. Για να το αποτρέψετε, προσθέστε το στο αρχείο σας .gitignore ώστε το Git να το παραλείπει κατά την καταχώριση αλλαγών:

.env

Σε περιβάλλοντα παραγωγής, οι μεταβλητές περιβάλλοντος συνήθως ρυθμίζονται απευθείας στις ρυθμίσεις της πλατφόρμας φιλοξενίας σας ή σε ένα διαχειριστή μυστικών, αντί σε ένα τοπικό αρχείο .env.

Ενημέρωση της ρύθμισης του Sequelize σας

Τώρα που έχετε ορίσει τις μεταβλητές περιβάλλοντος, ενημερώστε την αρχικοποίηση του Sequelize για να τις χρησιμοποιεί. Ξεκινήστε εισάγοντας και ρυθμίζοντας το dotenv στην αρχή του κύριου αρχείου του διακομιστή σας (π.χ., server.js):

require('dotenv').config();
const Sequelize = require('sequelize');

const sequelize = new Sequelize(
  process.env.DB_NAME,
  process.env.DB_USER,
  process.env.DB_PASSWORD,
  {
    host: process.env.DB_HOST,
    dialect: process.env.DB_DIALECT
  }
);

sequelize.authenticate().then(() => {
   console.log('Connection has been established successfully.');
}).catch((error) => {
   console.error('Unable to connect to the database:', error);
});
  1. Η γραμμή require('dotenv').config() φορτώνει όλες τις μεταβλητές που ορίζονται στο αρχείο .env στο process.env.
  2. Το Sequelize διαβάζει τις μεταβλητές περιβάλλοντος κατά την αρχικοποίηση μιας νέας στιγμιοτυπίας.
  3. Αυτό εξασφαλίζει ότι δεν εμφανίζονται ευαίσθητες πληροφορίες όπως ονόματα χρήστη ή κωδικοί πρόσβασης στον κώδικά σας.

Αυτή η προσέγγιση ενισχύει την ασφάλεια και επιτρέπει σε διαφορετικά περιβάλλοντα να χρησιμοποιούν μοναδικές ρυθμίσεις απλώς αλλάζοντας τις τιμές των μεταβλητών περιβάλλοντος.

Επαλήθευση της διαμόρφωσης

Μόλις ενημερώσετε τις ρυθμίσεις σας, μπορείτε να επαληθεύσετε τη σύνδεση εκτελώντας την εφαρμογή σας Node.js:

node server.js

Αν το αρχείο .env είναι ρυθμισμένο σωστά και ο διακομιστής MySQL εκτελείται, θα δείτε την εξής έξοδο:

Connection has been established successfully.

Αν εμφανιστεί κάποιο σφάλμα, ελέγξτε ξανά ότι:

  • Τα διαπιστευτήρια στο αρχείο σας .env ταιριάζουν με αυτά στην περίπτωση MySQL σας.
  • Ο διακομιστής MySQL λειτουργεί και είναι προσβάσιμος από τον υπολογιστή σας.
  • Το αρχείο .env βρίσκεται στη ρίζα του έργου σας και είναι σωστά μορφοποιημένο.

Βέλτιστες Πρακτικές για Ασφαλή Διαμόρφωση

Η χρήση μεταβλητών περιβάλλοντος είναι ένα ισχυρό πρώτο βήμα προς τη διαχείριση ασφαλών ρυθμίσεων. Για να διασφαλιστεί η συνεχής ασφάλεια και αξιοπιστία, εξετάστε τις ακόλουθες επιπλέον βέλτιστες πρακτικές:

  • Χρησιμοποιήστε ξεχωριστές ρυθμίσεις για κάθε περιβάλλον: Διατηρείτε διαφορετικά αρχεία .env για development, staging και production. Μπορείτε να τα ονομάσετε .env.development, .env.staging και .env.production.
  • Αξιοποιήστε διαχειριστές μυστικών: Για περιβάλλοντα παραγωγής, χρησιμοποιείτε διαχειριστές μυστικών αντί να αποθηκεύετε μυστικά σε αρχεία.
  • Επαληθεύστε τις μεταβλητές περιβάλλοντος: Χρησιμοποιήστε ένα εργαλείο διαμόρφωσης ή ένα σενάριο εκκίνησης που ελέγχει αν οι απαιτούμενες μεταβλητές είναι ορισμένες πριν εκτελεστεί η εφαρμογή. Αυτό βοηθά στην πρόληψη σφαλμάτων χρόνου εκτέλεσης.
  • Ανανεώνετε τα διαπιστευτήρια τακτικά: Ενημερώνετε τα διαπιστευτήρια της βάσης δεδομένων περιοδικά για να μειώσετε τον αντίκτυπο πιθανών διαρροών.
  • Περιορισμός πρόσβασης στη βάση δεδομένων: Διαμορφώστε τα δικαιώματα των χρηστών της βάσης δεδομένων ώστε να έχουν τα ελάχιστα απαραίτητα προνόμια για την εφαρμογή.

Με την υλοποίηση των μεταβλητών περιβάλλοντος και την ακολουθία αυτών των πρακτικών, εξασφαλίζετε ότι η εφαρμογή σας με Sequelize διατηρεί τόσο την ευελιξία όσο και την ασφάλεια σε περιβάλλοντα ανάπτυξης και παραγωγής.

Καλύτερες Πρακτικές για Μετανάστευση και Συγχρονισμό

Όταν εξελίσσετε ένα σχήμα βάσης δεδομένων, έχετε δύο βασικές προσεγγίσεις με το Sequelize: να γράφετε και να εκτελείτε ρητές μεταναστεύσεις, ή να χρησιμοποιείτε το sequelize.sync() για να αφήσετε το Sequelize να δημιουργεί αλλαγές στο σχήμα αυτόματα. Και οι δύο προσεγγίσεις είναι έγκυρες, αλλά εξυπηρετούν διαφορετικούς σκοπούς και έχουν τα πλεονεκτήματα και τα μειονεκτήματά τους. Ας κατανοήσουμε πότε να χρησιμοποιούμε την κάθε μία, πώς να γράφουμε ασφαλείς μεταναστεύσεις και πώς να τις εκτελούμε αξιόπιστα σε ανάπτυξη και παραγωγή.

Μεταναστεύσεις vs sequelize.sync() — πότε να χρησιμοποιήσετε ποιο

  • Μεταναστεύσεις (συνιστώνται για παραγωγή): Οι μεταναστεύσεις είναι σαφείς, εκδομένες αλλαγές στο σχήμα σας. Αποθηκεύονται σε έλεγχο πηγαίου κώδικα, ελέγχονται μέσω ανασκόπησης κώδικα και εκτελούνται ως μέρος της διαδικασίας ανάπτυξης. Χρησιμοποιήστε μεταναστεύσεις στην παραγωγή για οποιαδήποτε αλλαγή στο σχήμα που επηρεάζει την ακεραιότητα ή τη διαθεσιμότητα των δεδομένων.

  • sequelize.sync() (χρησιμοποιείται μόνο για ανάπτυξη και πρωτότυπα): Το sync() είναι βολικό για τοπική ανάπτυξη, δοκιμές και γρήγορα πρωτότυπα, επειδή μπορεί να δημιουργήσει ή να προσαρμόσει πίνακες αυτόματα. Ωστόσο, μην χρησιμοποιείτε sync({ force: true }) ή sync({ alter: true }) σε παραγωγή: αυτές οι επιλογές μπορούν να διαγράψουν δεδομένα ή να κάνουν επικίνδυνες αλλαγές χωρίς ελεγχόμενη διαδικασία επαναφοράς.

Εργαλεία: sequelize-cli και εκτελεστές μεταναστεύσεων

Το επίσημο CLI, sequelize-cli, είναι ο απλούστερος τρόπος για τη διαχείριση μεταναστεύσεων με το Sequelize. Για ομάδες που χρειάζονται μεγαλύτερο έλεγχο ή προσαρμοσμένες ροές εργασίας, το umzug είναι μια δημοφιλής εναλλακτική.

Για να εγκαταστήσετε και να αρχικοποιήσετε το CLI στο έργο σας, εκτελέστε:

npm install --save-dev sequelize-cli

npx sequelize-cli init

Αυτό δημιουργεί τους ακόλουθους φακέλους:

config/        # Stores database configuration files
models/        # Stores your Sequelize model definitions
migrations/    # Stores migration files
seeders/       # Stores seeder files for inserting initial data

Θα πρέπει να προσθέσετε αυτούς τους φακέλους στον έλεγχο εκδόσεων (εκτός από οποιαδήποτε αρχεία που περιέχουν διαπιστευτήρια). Αυτό εξασφαλίζει ότι κάθε περιβάλλον εκτελεί τις ίδιες αλλαγές στη βάση δεδομένων με συνέπεια.

Δημιουργία και Εκτέλεση Μετακινήσεων

Για να δημιουργήσετε ένα νέο αρχείο μετανάστευσης, χρησιμοποιήστε την ακόλουθη εντολή:

npx sequelize-cli migration:generate --name add-isbn-to-books

Αυτό δημιουργεί ένα αρχείο με χρονική σήμανση στον φάκελο migrations/. Ανοίξτε το αρχείο και ορίστε τι πρέπει να συμβεί όταν εφαρμόζετε τη μετανάστευση (up) και πώς να την αναιρέσετε (down):

module.exports = {
  async up(queryInterface, Sequelize) {
    await queryInterface.addColumn('books', 'isbn', {
      type: Sequelize.STRING
    });
  },
  async down(queryInterface) {
    await queryInterface.removeColumn('books', 'isbn');
  }
};
  • Η συνάρτηση up εφαρμόζει τη μετανάστευση (προσθέτει τη στήλη).
  • Η συνάρτηση down αναιρεί την αλλαγή (αφαιρεί τη στήλη).

Εκτελέστε τη μετανάστευση χρησιμοποιώντας:

npx sequelize-cli db:migrate

Για να αναιρέσετε την τελευταία μετανάστευση, χρησιμοποιήστε:

npx sequelize-cli db:migrate:undo

Μπορείτε επίσης να αναιρέσετε όλες τις μεταναστεύσεις στην ανάπτυξη εκτελώντας:

npx sequelize-cli db:migrate:undo:all

Γράφοντας ασφαλείς, ιδιότυπες μετανάστες

Ακολουθήστε αυτούς τους κανόνες κατά τη δημιουργία μεταναστεύσεων:

  • Συμπεριλάβετε τις λειτουργίες σε συναλλαγές όταν υποστηρίζονται από τη βάση δεδομένων. Αυτό εξασφαλίζει ότι η μετανάστευση είτε ολοκληρώνεται πλήρως είτε αναιρείται πλήρως σε περίπτωση σφάλματος.

    module.exports = {
      async up(queryInterface, Sequelize) {
        return queryInterface.sequelize.transaction(async (t) => {
          await queryInterface.addColumn('books', 'isbn', {
            type: Sequelize.STRING
          }, { transaction: t });
        });
      },
      async down(queryInterface) {
        return queryInterface.sequelize.transaction(async (t) => {
          await queryInterface.removeColumn('books', 'isbn', { transaction: t });
        });
      }
    };
  • Κρατήστε τις μεταναστεύσεις μικρές και στοχευμένες. Κάθε μετανάστευση θα πρέπει να εκτελεί μία μόνο λογική αλλαγή (προσθήκη μιας στήλης, δημιουργία ενός δείκτη, μετονομασία μιας στήλης). Οι μικρότερες μεταναστεύσεις είναι πιο εύκολες για ανασκόπηση, δοκιμή και επαναφορά.

  • Να είστε αμυντικοί και ιδιομορφικοί. Όταν είναι κατάλληλο, ελέγξτε για την ύπαρξη ώστε να αποφύγετε αποτυχίες σε περιβάλλοντα με εκτροπή. Χρησιμοποιήστε queryInterface.describeTable() ή ακατέργαστα ερωτήματα για να προστατεύσετε τις λειτουργίες.

  • Αποφύγετε τις καταστροφικές ενέργειες σε ένα βήμα. Για παράδειγμα, για να αφαιρέσετε μια στήλη με ασφάλεια, προσθέστε τη νέα στήλη, συμπληρώστε την, αλλάξτε τις αναγνώσεις στη νέα στήλη στον κώδικα της εφαρμογής και μόνο τότε αφαιρέστε την παλιά στήλη σε μια επόμενη μετανάστευση.

Μεταφορές μεγάλης διάρκειας και χωρίς διακοπές λειτουργίας

Οι μεγάλες πίνακες και οι λειτουργίες ευρετηρίου μπορούν να προκαλέσουν κλειδώματα. Χρησιμοποιήστε αυτές τις στρατηγικές για να μειώσετε τον αντίκτυπο:

  1. Προσθέστε πρώτα στήλες που μπορούν να έχουν τιμή null. Η προσθήκη μιας στήλης που μπορεί να έχει τιμή null είναι συνήθως γρήγορη. Αποφύγετε την προσθήκη στηλών με πολύπλοκες προεπιλεγμένες τιμές που ενεργοποιούν επανεγγραφή ολόκληρου του πίνακα.
  2. Συμπληρώστε σε μικρές δόσεις. Υλοποιήστε μια εργασία στο παρασκήνιο για να ενημερώσετε τις νέες στήλες σε τμήματα αντί να εκτελείτε ένα μεγάλο UPDATE.
  3. Δημιουργήστε ευρετήρια χωρίς αποκλειστικούς κλειδώματα όπου είναι δυνατόν. Χρησιμοποιήστε λειτουργίες ειδικές για τη βάση δεδομένων (για παράδειγμα, Postgres CONCURRENTLY και πρόσφατο MySQL online DDL) μέσω απλού SQL στις μεταναστεύσεις.
  4. Αναπτύξεις με σημαίες λειτουργιών. Ανάπτυξη κώδικα εφαρμογής που διαβάζει τη νέα στήλη πίσω από μια σημαία λειτουργίας. Αφού ολοκληρωθεί η συμπλήρωση δεδομένων και περάσουν τα τεστ, αλλάξτε τη σημαία και αργότερα αφαιρέστε το παλιό πεδίο.

Ανακλήσεις και επείγουσες επιδιορθώσεις

  • Παρέχετε μια down μετανάστευση. Κάθε up θα πρέπει να έχει αντίστροφο down που να τεκμηριώνει πώς να αναιρέσετε την αλλαγή. Ακόμη και αν σπάνια εκτελείτε down στην παραγωγή, λειτουργεί ως σαφές σχέδιο επαναφοράς.
  • Σχεδιάστε για εκτάκτες επαναφορές. Αν μια μετανάστευση προκαλέσει προβλήματα, να είστε έτοιμοι να επαναφέρετε πρώτα τον κώδικα της εφαρμογής και να αποκαταστήσετε τη βάση δεδομένων από τα αντίγραφα ασφαλείας αν χρειαστεί. Δοκιμάζετε τακτικά τις διαδικασίες επαναφοράς.

Κατάθεση δεδομένων και αλλαγές στο σχήμα

  • Διατηρήστε τους σπόρους ελάχιστους και σταθερούς. Χρησιμοποιήστε τους σπόρους για βασικές γραμμές αναζήτησης ή ρύθμισης. Αποφύγετε τη σπορά μεγάλου όγκου επιχειρηματικών δεδομένων μέσω μεταναστεύσεων.
  • Διαχωρίστε τους σπόρους από τις δομικές μεταναστεύσεις. Αν πρέπει να συμπληρώσετε δεδομένα που εξαρτώνται από μια αλλαγή στο σχήμα, προτιμήστε έναν επακόλουθο σπόρο, ώστε οι αρμοδιότητες να παραμένουν σαφείς.

CI, ανασκόπηση κώδικα και αυτοματοποίηση ανάπτυξης

  • Τρέξτε τις μεταναστεύσεις πρώτα σε CI και staging. Προσθέστε ένα βήμα στο CI που θα τρέχει τις μεταναστεύσεις σε μια προσωρινή βάση δεδομένων για να εντοπίζετε σφάλματα νωρίς.

  • Μεταχειριστείτε τις μεταναστεύσεις σαν κώδικα. Κάντε έλεγχο στίξης και ανασκόπηση των αρχείων μετανάστευσης στα pull requests. Συμπεριλάβετε αυτοματοποιημένους ελέγχους όπου είναι δυνατόν.

  • Αυτοματοποιήστε την εκτέλεση των μεταναστεύσεων κατά την ανάπτυξη. Βεβαιωθείτε ότι οι μεταναστεύσεις εκτελούνται πριν οι διαδικασίες της εφαρμογής αρχίσουν να δέχονται κίνηση. Παράδειγμα σκριπτ package.json:

    "scripts": {
      "migrate": "npx sequelize-cli db:migrate",
      "start": "node server.js",
      "deploy": "npm run migrate && npm run start"
    }

Σε περιβάλλοντα με container, εκτελέστε τις μεταναστεύσεις ως init container ή σε ένα deploy hook ώστε οι διαδικασίες του web να ξεκινούν μόνο μετά την ολοκλήρωση των μεταναστεύσεων.

Δοκιμή μεταναστεύσεων

  • Δοκιμάστε και τις δύο κατευθύνσεις. Εκτελέστε db:migrate και στη συνέχεια db:migrate:undo:all τοπικά και στο CI για να επιβεβαιώσετε ότι τόσο το up όσο και το down λειτουργούν.
  • Χρησιμοποιήστε προσωρινές βάσεις δεδομένων για δοκιμές. Προτιμήστε εφήμερες βάσεις δεδομένων ή κοντέινερ για καθορισμένες δοκιμές.

Η τήρηση αυτών των βέλτιστων πρακτικών εξασφαλίζει ότι οι μεταναστεύσεις σας στο Sequelize παραμένουν αξιόπιστες, ανιχνεύσιμες και ασφαλείς για μακροπρόθεσμα έργα.

Αντιμετώπιση προβλημάτων και συμβουλές απόδοσης

Ακόμη και με μια ισχυρή ρύθμιση, οι εφαρμογές Sequelize μπορούν μερικές φορές να αντιμετωπίσουν απροσδόκητα προβλήματα, όπως σφάλματα σύνδεσης με τη βάση δεδομένων, αποτυχίες μεταναστεύσεων, αργά εκτελούμενα ερωτήματα, αδιέξοδα ή συγκρούσεις ταυτόχρονης πρόσβασης. Αυτή η ενότητα παρέχει οδηγίες βήμα προς βήμα για τον εντοπισμό και την επίλυση αυτών των προβλημάτων, μαζί με βέλτιστες πρακτικές απόδοσης που σας βοηθούν να διατηρείτε την εφαρμογή σας σταθερή και αποτελεσματική.

Αντιμετώπιση Συνηθισμένων Προβλημάτων

1. Σφάλματα σύνδεσης

Πρόβλημα: Το Sequelize δεν μπορεί να συνδεθεί στη βάση δεδομένων MySQL και εμφανίζει σφάλματα όπως SequelizeConnectionError: connect ECONNREFUSED, Access denied for user ή SequelizeHostNotFoundError.

Πώς να διορθώσετε:

Ξεκινήστε επιβεβαιώνοντας ότι τα στοιχεία σύνδεσής σας είναι σωστά. Ελέγξτε ξανά τις τιμές στο αρχείο σας .env, περιλαμβανομένων του ονόματος της βάσης δεδομένων, του ονόματος χρήστη, του κωδικού πρόσβασης, του host και της θύρας. Ακόμα και ένα μικρό τυπογραφικό λάθος ή ένα κενό στο τέλος μπορεί να προκαλέσει αποτυχία σύνδεσης στο Sequelize.

Στη συνέχεια, βεβαιωθείτε ότι ο διακομιστής MySQL λειτουργεί και ακούει στην προεπιλεγμένη θύρα (3306). Μπορείτε να δοκιμάσετε τη σύνδεση κάνοντας χειροκίνητη είσοδο:

mysql -u your_username -p -h your_host -P 3306

Αν αυτή η εντολή αποτύχει, το πρόβλημα πιθανότατα βρίσκεται στην υπηρεσία MySQL σας ή στα διαπιστευτήριά σας.

Αν χρησιμοποιείτε το πακέτο dotenv, βεβαιωθείτε ότι το require('dotenv').config() εμφανίζεται πριν από την αρχικοποίηση του Sequelize. Αυτό το βήμα διασφαλίζει ότι όλες οι μεταβλητές περιβάλλοντος είναι διαθέσιμες κατά την εκτέλεση.

Τέλος, για απομακρυσμένες συνδέσεις, επαληθεύστε τις ρυθμίσεις του τείχους προστασίας ή τους κανόνες της ομάδας ασφαλείας. Ο διακομιστής MySQL πρέπει να δέχεται εισερχόμενες συνδέσεις από τον κεντρικό υπολογιστή της εφαρμογής σας.

2. Αποτυχίες Μετανάστευσης

Πρόβλημα: Εκτελείτε npx sequelize-cli db:migrate ή sequelize.sync() και συναντάτε σφάλματα όπως ελλείποντες πίνακες, διπλές στήλες ή ασυμφωνίες στο σχήμα.

Πώς να διορθώσετε:

Τα προβλήματα με τις μεταναστεύσεις συνήθως προκύπτουν όταν τα αρχεία εκτελούνται με λάθος σειρά ή περιέχουν σφάλματα στις λειτουργίες SQL. Το Sequelize επεξεργάζεται τις μεταναστεύσεις βάσει των χρονικών σημάνσεων στα ονόματα αρχείων, οπότε επιβεβαιώστε ότι τα αρχεία έχουν σωστά ονόματα.

Αν μια μετανάστευση αποτύχει, εξετάστε λεπτομερώς το μήνυμα σφάλματος. Στη συνέχεια, επαναφέρετε με ασφάλεια την τελευταία μετανάστευση χρησιμοποιώντας:

npx sequelize-cli db:migrate:undo

Μετά την επιδιόρθωση του αρχείου μετανάστευσης, τρέξτε το ξανά.

Πάντα να περικλείετε τη λογική μετανάστευσης μέσα σε μια συναλλαγή για να εξασφαλίσετε ατομικότητα: είτε όλες οι αλλαγές επιτυγχάνουν είτε καμία. Πριν εκτελέσετε τις μεταναστεύσεις στην παραγωγή, δοκιμάστε τις διεξοδικά σε μια δοκιμαστική ή τοπική βάση δεδομένων για να επιβεβαιώσετε την ορθότητά τους.

3. Προβλήματα Συγχρονισμού Μοντέλου

Πρόβλημα: Τα μοντέλα σας στο Sequelize και το σχήμα της βάσης δεδομένων δεν ταιριάζουν, οδηγώντας σε ελλείποντες στήλες, λανθασμένους τύπους δεδομένων ή παρωχημένους πίνακες.

Πώς να διορθώσετε:

Αποφύγετε τη χρήση του sequelize.sync({ force: true }) σε παραγωγικό περιβάλλον, καθώς θα διαγράψει και θα δημιουργήσει ξανά τους πίνακες, προκαλώντας μη αναστρέψιμη απώλεια δεδομένων. Ομοίως, χρησιμοποιείτε το sequelize.sync({ alter: true }) με προσοχή· μπορεί να τροποποιήσει το σχήμα απρόβλεπτα.

Αντ' αυτού, προτιμήστε ξεκάθαρες μεταναστεύσεις που ορίζουν σαφώς κάθε αλλαγή σχήματος. Για να συγκρίνετε τα μοντέλα σας με την πραγματική δομή της βάσης δεδομένων, χρησιμοποιήστε:

await queryInterface.describeTable('tableName');

Αυτό βοηθά στον εντοπισμό των ασυμφωνιών πριν επηρεάσουν την παραγωγή.

4. Σφάλματα Ερωτημάτων και Χρονικού Περιορισμού

Πρόβλημα: Βλέπετε σφάλματα που σχετίζονται με χρόνο αναμονής, όπως Σφάλμα χρόνου σύνδεσης ή Πολύ πολλές συνδέσεις.

Πώς να διορθώσετε:

Τα προβλήματα χρονικού ορίου συχνά προκαλούνται από εξαντλημένες δεξαμενές συνδέσεων ή μη κλειστές συνδέσεις. Βεβαιωθείτε ότι όλα τα ερωτήματα Sequelize περιμένουν σωστά ώστε οι συνδέσεις να επιστρέφουν στη δεξαμενή μετά τη χρήση.

Μπορείτε επίσης να προσαρμόσετε τη ρύθμιση της δεξαμενής του Sequelize για να ταιριάζει καλύτερα στο φόρτο εργασίας της εφαρμογής σας:

const sequelize = new Sequelize(DB_NAME, DB_USER, DB_PASSWORD, {
  host: DB_HOST,
  dialect: 'mysql',
  pool: {
    max: 10,
    min: 0,
    acquire: 30000,
    idle: 10000
  }
});

Αν η εφαρμογή σας διαχειρίζεται πολλούς ταυτόχρονους χρήστες, σκεφτείτε να αυξήσετε την παράμετρο max_connections του MySQL στη ρύθμιση της βάσης δεδομένων σας. Παρακολουθείτε τις ενεργές συνδέσεις χρησιμοποιώντας SHOW PROCESSLIST; στο MySQL για να εντοπίσετε διαρροές ή ανενεργές συνεδρίες.

5. Αργή Απόδοση Ερωτημάτων

Πρόβλημα: Ορισμένα ερωτήματα διαρκούν σημαντικά περισσότερο από ό,τι αναμένεται, προκαλώντας αργές απαντήσεις API ή υψηλή καθυστέρηση.

Πώς να διαγνώσετε:

Ξεκινήστε προσδιορίζοντας ποιες ερωτήσεις είναι αργές. Μπορείτε να καταγράψετε όλες τις ερωτήσεις που εκτελεί το Sequelize ενεργοποιώντας προσωρινά την καταγραφή:

const sequelize = new Sequelize(..., { logging: console.log });

Στη συνέχεια, χρησιμοποιήστε τη δήλωση EXPLAIN του MySQL για να κατανοήσετε πώς η βάση δεδομένων εκτελεί το ερώτημα:

EXPLAIN SELECT * FROM users WHERE email = 'user@example.com';

Αν η έξοδος δείχνει «πλήρη σάρωση πίνακα», τότε το ερώτημα δεν έχει ευρετήριο.

Μπορείτε επίσης να ενεργοποιήσετε το αρχείο καταγραφής αργών ερωτημάτων του MySQL για να καταγράψει αυτόματα τις αργές λειτουργίες:

SET GLOBAL slow_query_log = 'ON';
SET GLOBAL long_query_time = 1;

Πώς να διορθώσετε:

Προσθέστε ευρετήρια σε στήλες που ερωτώνται συχνά (ιδιαίτερα αυτές που χρησιμοποιούνται σε WHERE, JOIN και ORDER BY εκφράσεις). Αποφύγετε το SELECT *, αντίθετα, ανακτήστε ρητά μόνο τα πεδία που χρειάζεστε χρησιμοποιώντας την επιλογή attributes.

Αν το Sequelize δημιουργεί μη αποδοτικά ερωτήματα με περιττά joins, ξαναγράψτε το ερώτημα χρησιμοποιώντας raw SQL. Για μεγάλα reports ή ερωτήματα ανάλυσης, σπάστε τα σε μικρότερα βήματα ή χρησιμοποιήστε εργαλεία caching όπως το Redis για να αποθηκεύετε επαναλαμβανόμενα αποτελέσματα.

6. Αδιέξοδα και Σφάλματα Ταυτόχρονης Εκτέλεσης

Πρόβλημα: Λαμβάνετε σφάλματα όπως Deadlock found when trying to get lock; try restarting transaction, ειδικά υπό μεγάλη φόρτωση.

Πώς να διαγνώσετε:

Ελέγξτε την κατάσταση του InnoDB στο MySQL για να εντοπίσετε ποιες ερωτήσεις ή πίνακες εμπλέκονταν:

SHOW ENGINE INNODB STATUS\G

Αυτό το αποτέλεσμα περιλαμβάνει λεπτομερείς πληροφορίες σχετικά με πρόσφατα deadlocks και αναμονές κλειδώματος. Μπορείτε επίσης να ενεργοποιήσετε γενικά ή συναλλακτικά logs για να εξετάσετε τη σειρά των ερωτημάτων που οδήγησαν στο πρόβλημα.

Πώς να διορθώσετε:

Τα deadlocks συμβαίνουν όταν δύο ή περισσότερες συναλλαγές περιμένουν τα κλειδώματα η μία της άλλης. Για να τα ελαχιστοποιήσετε:

  1. Κράτα τις συναλλαγές όσο το δυνατόν πιο σύντομες. Μην καλείς εξωτερικές υπηρεσίες ή εκτελείς βαριές υπολογιστικές διαδικασίες ενώ κρατάς ένα κλείδωμα.

  2. Πάντα προσπελάζετε πίνακες και γραμμές με την ίδια σειρά σε όλες τις συναλλαγές για να αποφύγετε κυκλικές αναμονές.

  3. Για επαναλαμβανόμενα αδιέξοδα, υλοποιήστε έναν απλό μηχανισμό επαναπροσπάθειας με εκθετική καθυστέρηση:

    async function runWithRetry(fn, retries = 3) {
      for (let i = 0; i < retries; i++) {
        try {
          return await fn();
        } catch (err) {
          if (isDeadlockError(err) && i < retries - 1) {
            await sleep(100 * (i + 1));
            continue;
          }
          throw err;
        }
      }
    }
  4. Χρησιμοποιείτε κλειδώματα επιπέδου γραμμής (SELECT ... FOR UPDATE) μόνο όταν είναι απαραίτητο και τα απελευθερώνετε αμέσως.

  5. Διαίρετε μεγάλες συναλλαγές σε μικρότερες παρτίδες για να μειώσετε τις συγκρούσεις.

  6. Ρυθμίστε τα επίπεδα απομόνωσης των συναλλαγών, αν κρίνεται σκόπιμο, αλλά μόνο μετά την επιβεβαίωση ότι αυτό δεν θα επηρεάσει τη συνοχή των δεδομένων.

Συμβουλές Βελτιστοποίησης Απόδοσης

Τα προβλήματα απόδοσης συχνά προέρχονται από αναποτελεσματικά ερωτήματα, ελλιπείς δείκτες ή κακή διαχείριση των συνδέσεων. Ακολουθούν μερικές πρακτικές συμβουλές για τη βελτίωση της απόδοσης του Sequelize χωρίς να θυσιάζεται η σαφήνεια ή η δυνατότητα συντήρησης.

1. Βελτιστοποίηση Ερωτημάτων

Γράφε ερωτήματα που ζητούν μόνο ό,τι χρειάζεται. Η ανάκτηση περιττών δεδομένων αυξάνει τη χρήση μνήμης και επιβραδύνει τις απαντήσεις. Χρησιμοποίησε attributes για να περιορίσεις τα πεδία:

const users = await User.findAll({ attributes: ['id', 'name'] });

Πάντα φιλτράρετε τα αποτελέσματα χρησιμοποιώντας ευρετηριασμένες στήλες και αποφύγετε ευρείες αναζητήσεις όπως LIKE '%term%' όταν είναι δυνατόν.

2. Χρησιμοποιήστε τα Ευρετήρια Αποτελεσματικά

Οι δείκτες κάνουν την αναζήτηση ταχύτερη αλλά μπορεί να επιβραδύνουν τις εγγραφές. Προσθέστε δείκτες μόνο εκεί όπου παρέχουν μετρήσιμα οφέλη. Αναλύστε την απόδοση των ερωτημάτων με το EXPLAIN του MySQL για να επαληθεύσετε τις βελτιώσεις πριν και μετά την προσθήκη ενός δείκτη:

await queryInterface.addIndex('users', ['email']);

3. Ρυθμίστε το Pool Συνδέσεων

Η δεξαμενή συνδέσεων καθορίζει πόσες συνδέσεις βάσης δεδομένων διατηρεί το Sequelize.

  • Για μικρές εφαρμογές, 5–10 συνδέσεις είναι συνήθως αρκετές.
  • Για συστήματα υψηλού φόρτου, αυξήστε το μέγεθος της δεξαμενής και προσαρμόστε τα χρονικά όρια για να αποτρέψετε μποτιλιαρίσματα συνδέσεων. Παρακολουθείτε τη χρήση τακτικά χρησιμοποιώντας το SHOW PROCESSLIST; του MySQL.

4. Ενεργοποίηση Καταγραφής και Παρακολούθησης

Ενεργοποιήστε προσωρινά την καταγραφή του Sequelize για να ελέγξετε τα ερωτήματα SQL. Χρησιμοποιήστε το αρχείο καταγραφής αργών ερωτημάτων του MySQL για να εντοπίσετε τα ερωτήματα που υπερβαίνουν το όριο απόδοσής σας. Για παρακολούθηση σε πραγματικό χρόνο, ενσωματώστε εργαλεία παρακολούθησης όπως το PM2, το New Relic ή το Datadog για να μετρήσετε την καθυστέρηση και τη χρήση πόρων.

5. Αποθήκευση Συχνών Ερωτημάτων

Αποθηκεύστε προσωρινά τα αποτελέσματα για δεδομένα που δεν αλλάζουν συχνά. Εργαλεία όπως το Redis ή το Memcached μειώνουν τα πλήγματα στη βάση δεδομένων και βελτιώνουν τους χρόνους απόκρισης, ιδιαίτερα για εργασίες με μεγάλο φόρτο ανάγνωσης.

6. Σελιδοποίηση Αποτελεσμάτων

Τα μεγάλα σύνολα αποτελεσμάτων καταναλώνουν σημαντική μνήμη. Πάντα να χρησιμοποιείτε σελιδοποίηση στα ερωτήματα στις APIs:

const users = await User.findAll({ limit: 50, offset: 100 });

Η σελιδοποίηση διατηρεί τις απαντήσεις ελαφριές και συνεκτικές υπό φόρτο.

7. Χρησιμοποιήστε Ακατέργαστα Ερωτήματα για Σύνθετες Δράσεις

Αν η αφαίρεση του Sequelize έχει ως αποτέλεσμα αναποτελεσματικό SQL για μια συγκεκριμένη περίπτωση χρήσης, εκτελέστε ένα άμεσο SQL query:

const [results] = await sequelize.query('SELECT name FROM users WHERE active = 1');

Χρησιμοποιείτε τις ακατέργαστες ερωτήσεις με φειδώ και τεκμηριώστε τες ξεκάθαρα για μελλοντική συντήρηση.

Συχνές Ερωτήσεις

1. Τι είναι το Sequelize στο Node.js;

Το Sequelize είναι ένας αντικειμενο-σχεσιακός mapper (ORM) για το Node.js που παρέχει μια υψηλού επιπέδου, βασισμένη σε JavaScript API για εργασία με βάσεις δεδομένων SQL όπως MySQL, PostgreSQL, SQLite και MariaDB. Αντί να γράφετε ακατέργαστο SQL για κάθε λειτουργία, ορίζετε μοντέλα που αντιστοιχούν σε πίνακες βάσης δεδομένων και χρησιμοποιείτε μεθόδους των μοντέλων για εισαγωγή, αναζήτηση, ενημέρωση και διαγραφή εγγραφών. Το Sequelize υποστηρίζει επίσης συσχετίσεις (σχέσεις μεταξύ μοντέλων), συναλλαγές, μεταναστεύσεις και ακατέργαστα queries όταν χρειάζεστε άμεσο SQL.

2. Πώς συνδέω το Sequelize με το MySQL;

Για να συνδέσετε το Sequelize με το MySQL, δημιουργείτε μια εμφάνιση (instance) του Sequelize με τα διαπιστευτήρια και τις επιλογές της βάσης δεδομένων σας. Σε ένα αρχείο Node.js, κάνετε require το Sequelize, προαιρετικά φορτώνετε μεταβλητές περιβάλλοντος, και στη συνέχεια το δημιουργείτε με το όνομα της βάσης δεδομένων, το όνομα χρήστη, τον κωδικό πρόσβασης και τις επιλογές host/dialect. Για παράδειγμα:

require('dotenv').config();
const { Sequelize } = require('sequelize');

const sequelize = new Sequelize(
  process.env.DB_NAME,
  process.env.DB_USER,
  process.env.DB_PASSWORD,
  {
    host: process.env.DB_HOST || 'localhost',
    dialect: 'mysql'
  }
);

await sequelize.authenticate();
console.log('Connected to the database successfully!');

Να φυλάτε πάντα τα στοιχεία σύνδεσης εκτός του ελέγχου πηγής (για παράδειγμα, σε ένα αρχείο .env ή σε έναν διαχειριστή μυστικών).

3. Πώς δημιουργώ και συγχρονίζω μοντέλα στο Sequelize;

Στο Sequelize, τα μοντέλα αντιπροσωπεύουν πίνακες. Τα ορίζετε χρησιμοποιώντας το sequelize.define() ή επεκτείνοντας την κλάση Model. Μετά από αυτό, μπορείτε να τα συγχρονίσετε με τη βάση δεδομένων σας ώστε το Sequelize να δημιουργεί αυτόματα τους πίνακες (ιδανικό για ανάπτυξη). Ακολουθεί ένα μικρό παράδειγμα:

const { DataTypes } = require('sequelize');

const Book = sequelize.define('Book', {
  title: { type: DataTypes.STRING, allowNull: false },
  author: { type: DataTypes.STRING, allowNull: false },
  releaseDate: DataTypes.DATEONLY
});

// Create the table if it does not exist
await sequelize.sync();

Για περιβάλλοντα παραγωγής, είναι καλύτερο να χρησιμοποιείτε μεταναστεύσεις ώστε να έχετε έλεγχο εκδόσεων για τις αλλαγές του σχήματος.

4. Πώς χρησιμοποιώ το Sequelize με το Express;

Σε μια εφαρμογή Express, αρχικοποιήστε το Sequelize σε ένα ξεχωριστό αρχείο (όπως db.js), εξάγετε την συνδεδεμένη παρουσία και τα μοντέλα, και τα εισάγετε όπου τα χρειάζεστε στους χειριστές διαδρομών ή στους ελεγκτές σας. Χρησιμοποιήστε async/await στους χειριστές διαδρομών για να καλέσετε μεθόδους μοντέλων του Sequelize, και χειριστείτε τα σφάλματα με try/catch ή με ένα μεσαίο λογισμικό σφαλμάτων. Δείτε πώς φαίνεται αυτό στην πράξη:

// db.js
const sequelize = new Sequelize(...);
const User = sequelize.define(...);
module.exports = { sequelize, User };

// app.js
const { User } = require('./db');
app.get('/users', async (req, res) => {
  const users = await User.findAll();
  res.json(users);
});

Βεβαιωθείτε ότι θα εκτελέσετε τις μεταναστεύσεις ή θα καλέσετε το sequelize.sync() πριν ξεκινήσετε τον διακομιστή Express, ώστε οι πίνακες της βάσης δεδομένων σας να υπάρχουν όταν γίνονται αιτήματα.

5. Ποια είναι η διαφορά μεταξύ του Sequelize και των απλών ερωτημάτων SQL;

Το Sequelize σας επιτρέπει να γράφετε λογική βάσης δεδομένων σε JavaScript, ενώ το raw SQL σημαίνει ότι γράφετε απευθείας δηλώσεις SQL. Το Sequelize κάνει τον κώδικά σας πιο καθαρό και ευκολότερο στη συντήρηση, επειδή μπορείτε να ορίσετε μοντέλα και σχέσεις μία φορά και να τα χρησιμοποιήσετε σε όλη την εφαρμογή σας. Το raw SQL σας δίνει περισσότερο έλεγχο και μερικές φορές μπορεί να είναι ταχύτερο για πολύπλοκες ερωτήσεις.

Συνοπτικά, χρησιμοποιήστε το Sequelize για τις περισσότερες καθημερινές εργασίες και χρησιμοποιήστε ακατέργαστο SQL όταν χρειάζεται να βελτιστοποιήσετε την απόδοση ή να εκτελέσετε κάτι που δεν μπορεί να εκφράσει εύκολα το Sequelize.

6. Πώς μπορώ να ορίσω συσχετίσεις στο Sequelize;

Το Sequelize καθιστά εύκολο το να περιγράψετε τις σχέσεις μεταξύ των πινάκων. Μπορείτε να δημιουργήσετε σχέσεις ένα προς ένα, ένα προς πολλά ή πολλά προς πολλά χρησιμοποιώντας απλές μεθόδους όπως hasOne, hasMany και belongsToMany. Για παράδειγμα:

// One to one
User.hasOne(Profile);
Profile.belongsTo(User);

// One to many
Author.hasMany(Book);
Book.belongsTo(Author);

// Many to many
Student.belongsToMany(Course, { through: 'StudentCourse' });
Course.belongsToMany(Student, { through: 'StudentCourse' });

Μόλις οριστεί, μπορείτε να χρησιμοποιήσετε το include στα ερωτήματά σας για να ανακτήσετε αυτόματα σχετικά δεδομένα.

7. Πώς διαχειρίζομαι τις μετεγκαταστάσεις και τις αλλαγές στο σχήμα;

Στην ανάπτυξη, μπορείτε να χρησιμοποιήσετε το sequelize.sync() για να δημιουργήσετε γρήγορα πίνακες. Αλλά στην παραγωγή, θα πρέπει πάντα να χρησιμοποιείτε τις μεταναστεύσεις (migrations). Οι μεταναστεύσεις είναι εκδομένες αρχεία που περιγράφουν πώς αλλάζει το σχήμα της βάσης δεδομένων σας με την πάροδο του χρόνου, παρόμοια με τον τρόπο που οι δεσμεύσεις (commits) στο Git παρακολουθούν τις αλλαγές στον κώδικα.

Μπορείτε να δημιουργήσετε μια μετανάστευση με το Sequelize CLI:

npx sequelize-cli migration:generate --name add-users-table

Κάθε μετανάστευση έχει μεθόδους up και down, η μία για την εφαρμογή της αλλαγής και η άλλη για την αναιρέσή της. Εκτελέστε τις μεταναστεύσεις σας με:

npx sequelize-cli db:migrate

Με αυτόν τον τρόπο, όλοι στην ομάδα σας (και κάθε ανάπτυξη) διατηρούν την ίδια δομή βάσης δεδομένων.

Χρησιμοποίησε το sequelize.sync() για γρήγορα πειράματα, αλλά κράτα τις μεταναστεύσεις μόλις η εφαρμογή σου είναι ζωντανή, γιατί είναι πιο ασφαλείς, αναστρέψιμες και πιο εύκολες στην παρακολούθηση.

Συμπέρασμα

Σε αυτό το σεμινάριο, ρυθμίζετε το Sequelize με Node.js και MySQL για να διαχειρίζεστε δεδομένα μέσω μοντέλων, συσχετίσεων και μεταναστεύσεων. Επίσης, ασφαλίσατε τα στοιχεία σύνδεσης της βάσης δεδομένων σας με μεταβλητές περιβάλλοντος και εξερευνήσατε τις βέλτιστες πρακτικές για αντιμετώπιση προβλημάτων και βελτιστοποίηση απόδοσης.

Με αυτά τα βήματα, έχετε τώρα μια σταθερή βάση για την ανάπτυξη και τη διατήρηση ασφαλών, αποδοτικών εφαρμογών Node.js που χρησιμοποιούν Sequelize και MySQL για διαχείριση δεδομένων.

Για να μάθετε περισσότερα σχετικά με το Sequelize, δείτε την τεκμηρίωση του προϊόντος. Για περισσότερα τέτοια μαθήματα Node.js, δείτε τα παρακάτω άρθρα:

  • Πώς να Ρυθμίσετε έναν Διακομιστή GraphQL στο Node.js με Apollo Server και Sequelize
  • Πώς να Υλοποιήσετε Caching στο Node.js Χρησιμοποιώντας το Redis
  • Πώς να Δημιουργήσετε έναν Διακομιστή Ιστοσελίδων σε Node.js με το Μονάδα HTTP

Ευχαριστούμε που μάθατε με την Κοινότητα Linux-Console.net.