Cara Menggunakan Sequelize dengan Node.js dan MySQL
Pengarang memilih Dana Internet Terbuka/Ucapan Bebas untuk menerima sumbangan sebagai sebahagian daripada program Menulis untuk Sumbangan.
Pengenalan
Sequelize adalah Object Relational Mapper berasaskan Node.js yang memudahkan kerja dengan pangkalan data MySQL, MariaDB, SQLite, PostgreSQL, dan banyak lagi. Object Relational Mapper melaksanakan fungsi seperti mengendalikan rekod pangkalan data dengan mewakili data sebagai objek. Sequelize mempunyai mekanisme migrasi yang kuat yang boleh menukar skema pangkalan data sedia ada kepada versi baru. Secara keseluruhannya, Sequelize menyediakan sokongan yang cemerlang untuk penyegerakan pangkalan data, muat turun awal (eager loading), perkaitan, transaksi, dan migrasi pangkalan data sambil mengurangkan masa pembangunan dan mencegah injeksi SQL.
Dalam tutorial ini, anda akan memasang dan mengkonfigurasi Sequelize dengan MySQL dalam persekitaran pembangunan tempatan anda. Seterusnya, anda akan menggunakan Sequelize untuk membuat pangkalan data dan model, serta melaksanakan operasi insert, select, dan delete. Kemudian, anda akan membuat hubungan Sequelize untuk hubungan satu-ke-satu, satu-ke-banyak, dan banyak-ke-banyak. Akhir sekali, anda akan membuat pertanyaan mentah Sequelize untuk penggantian array dan objek. Selain daripada asas-asas ini, tutorial ini juga merangkumi konfigurasi pangkalan data yang selamat menggunakan pemboleh ubah persekitaran, mengurus perubahan skema dengan selamat melalui migrasi, dan amalan terbaik untuk menyelesaikan masalah serta pengoptimuman prestasi.
Sebarkan aplikasi frontend anda dari GitHub menggunakan Platform Aplikasi Linux-Console.net. Biarkan Linux-Console.net menumpukan kepada pengembangan aplikasi anda.
Perkara Penting:
- Sequelize menyediakan cara mudah untuk berinteraksi dengan MySQL menggunakan model dan bukannya SQL mentah, menjadikan operasi pangkalan data lebih mudah dan teratur.
- Menyimpan kelayakan pangkalan data dalam pembolehubah persekitaran memastikan maklumat sensitif selamat dan tidak termasuk dalam kawalan versi.
- Menggunakan migrasi untuk kemas kini skema adalah lebih selamat daripada bergantung pada
sequelize.sync(), terutamanya dalam persekitaran pengeluaran. - Sequelize memudahkan untuk mendefinisikan hubungan satu-ke-satu, satu-ke-banyak, dan banyak-ke-banyak antara model.
- Query SQL mentah masih boleh digunakan apabila anda memerlukan lebih kawalan atau prestasi yang lebih baik untuk operasi pangkalan data yang kompleks.
- Masalah paling biasa dengan Sequelize, seperti kegagalan sambungan atau ralat migrasi, boleh diselesaikan dengan memeriksa pembolehubah persekitaran, menyemak log, dan menggunakan alat MySQL seperti
EXPLAINdanSHOW PROCESSLIST. - Prestasi boleh ditingkatkan dengan mengoptimumkan pertanyaan, menambah indeks yang sesuai, melaras kolam sambungan, dan menyimpan data yang kerap diakses dalam cache.
- Menguji migrasi, menambah pengendalian ralat, dan memantau prestasi pangkalan data membantu memastikan aplikasi Sequelize boleh dipercayai dan sedia untuk produksi.
Prasyarat
Untuk melengkapkan tutorial ini, anda akan memerlukan:
- Satu persekitaran pembangunan yang menjalankan Node.js. Untuk menyiapkannya, ikuti tutorial Cara Memasang Node.js dan Mewujudkan Persekitaran Pembangunan Tempatan untuk sistem operasi anda.
- MySQL dipasang dalam persekitaran kerja anda. Ikuti tutorial Cara Memasang MySQL untuk persekitaran anda, termasuk langkah-langkah untuk membuat pengguna.
- Familiar dengan JavaScript dan pertanyaan MySQL, yang boleh anda kembangkan dengan siri How To Code in JavaScript dan tutorial Pengenalan kepada Pertanyaan dalam MySQL.
- Pemahaman asas tentang konsep pangkalan data hubungan, yang boleh anda temui dalam tutorial, Memahami Pangkalan Data Berhubung.
Tutorial ini diuji pada versi Node.js v24.11.1 dan versi npm 11.6.2.
Memasang dan Mengkonfigurasi Sequelize
Dalam langkah ini, anda akan memasang Sequelize dan membuat sambungan ke pangkalan data MySQL anda. Untuk melakukannya, pertama anda akan membuat aplikasi Node.js. Kemudian, anda akan memasang Sequelize, mengkonfigurasi pangkalan data MySQL, dan membangunkan aplikasi yang mudah.
Memasang Sequelize
Mulakan dengan membuat folder projek. Dalam contoh ini, anda boleh menggunakan hello-world. Setelah folder dibuat, navigasi ke folder tersebut menggunakan terminal:
mkdir hello-world
cd hello-worldKemudian, buat aplikasi Node.js contoh menggunakan arahan berikut:
npm initSeterusnya, anda akan diminta untuk menjawab beberapa soalan tetapan. Gunakan hasil berikut untuk konfigurasi anda. Tekan ENTER untuk menggunakan nilai lalai yang dipaparkan dan pastikan untuk menetapkan titik masuk utama sebagai server.js. Ini mewujudkan struktur projek yang mudah untuk dikekalkan.
Output akan kelihatan seperti berikut, yang akan mengisi fail 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"
}Seterusnya, buat satu fail server.js kosong di dalam folder projek:
touch server.jsSelepas mengikuti langkah-langkah sebelum ini, struktur folder akhir anda akan kelihatan seperti ini:
hello-world/
├─ package.json
├─ server.js
Sekarang anda boleh memasang Sequelize dengan arahan berikut:
npm i sequelizeSelepas kemas kini ini, fail package.json kini kelihatan seperti ini:
{
"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"
}
}Dalam bahagian dependencies, anda sekarang akan melihat kebergantungan Sequelize.
Anda telah menyiapkan projek dan memasang Sequelize. Seterusnya, anda akan membuat pangkalan data contoh untuk disambungkan.
Mewujudkan Pangkalan Data Contoh
Sebagai sebahagian daripada prasyarat, anda telah memasang dan mengkonfigurasi MySQL, yang termasuk membuat pengguna. Kini anda akan membuat pangkalan data kosong.
Untuk melakukan itu, pertama sekali, anda perlu log masuk ke instance MySQL anda. Jika anda menjalankannya dari jauh, anda boleh menggunakan alat pilihan anda. Jika anda menggunakan instance MySQL yang berjalan secara tempatan, anda boleh menggunakan arahan berikut, menggantikan your_username dengan nama pengguna MySQL anda:
mysql -u your_username -p-u ialah nama pengguna dan pilihan -p digunakan jika akaun dilindungi dengan kata laluan.
Pelayan MySQL akan meminta kata laluan pangkalan data anda. Taipkan kata laluan anda dan tekan ENTER.
Setelah anda log masuk, cipta sebuah pangkalan data bernama hello_world_db menggunakan arahan berikut:
CREATE DATABASE hello_world_db;Untuk mengesahkan sama ada anda telah berjaya mencipta pangkalan data, anda boleh menggunakan arahan ini:
SHOW DATABASES;
Keluaran anda akan serupa dengan ini:
+--------------------+
| Database |
+--------------------+
| hello_world_db |
| information_schema |
| mysql |
| performance_schema |
| sys |
+--------------------+Selepas membuat pangkalan data sampel, putuskan sambungan daripada pelayan MySQL:
mysql> QUITSekarang, anda perlu memasang pemacu secara manual untuk pangkalan data pilihan anda. Oleh kerana Sequelize hanya menyediakan ciri ORM, ia tidak termasuk pemacu pangkalan data terbina dalam. Oleh itu, anda perlu memasang pemacu mengikut pilihan anda. Untuk melakukannya, navigasi ke direktori projek menggunakan terminal dan pasangkan pemacu MySQL ke dalam projek menggunakan arahan berikut:
npm install --save mysql2Dalam kes ini, anda menggunakan pemacu untuk MySQL.
Nota: Oleh kerana tutorial ini menggunakan MySQL sebagai pangkalan data, anda menggunakan pemacu untuk itu. Bergantung pada pangkalan data anda, anda boleh memasang pemacu secara manual seperti berikut:
npm install --save pg pg-hstore # Postgresnpm install --save mysql2npm install --save mariadbnpm install --save sqlite3npm install --save tedious # Microsoft SQL Server
Sekarang anda mempunyai pangkalan data contoh, anda boleh membuat aplikasi Sequelize pertama anda dengan sambungan pangkalan data.
Menyambung ke Pangkalan Data MySQL
Dalam bahagian ini, anda akan menyambungkan aplikasi Node.js kepada pangkalan data MySQL menggunakan Sequelize.
Untuk menyambung ke pangkalan data, buka server.js untuk disunting menggunakan nano atau penyunting kod pilihan anda:
nano server.jsDi sini, anda akan membuat sambungan pangkalan data dalam aplikasi anda menggunakan instance Sequelize. Dalam kaedah new Sequelize(), masukkan parameter pelayan MySQL dan kelayakan pangkalan data seperti berikut, menggantikan DATABASE_USERNAME dan DATABASE_PASSWORD dengan kelayakan pengguna MySQL anda:
const Sequelize = require("sequelize");
const sequelize = new Sequelize(
'hello_world_db',
'DATABASE_USERNAME',
'DATABASE_PASSWORD',
{
host: 'DATABASE_HOST',
dialect: 'mysql'
}
);host adalah tempat pelayan MySQL dihoskan, jadi anda perlu memberikan URL pelayan atau alamat IP. Jika anda menggunakan pelayan MySQL yang dipasang secara tempatan, anda boleh menggantikan DATABASE_HOST dengan localhost atau 127.0.0.1 sebagai nilainya.
Begitu juga, jika anda menggunakan pelayan jauh, pastikan untuk menggantikan nilai sambungan pangkalan data dengan maklumat pelayan jauh yang sesuai.
Nota: Jika anda menggunakan perisian pelayan pangkalan data lain, anda boleh menggantikan parameter dialek mengikut kesesuaiannya.
Seterusnya, panggil kaedah authenticate() berasaskan janji untuk memulakan sambungan pangkalan data ke aplikasi. Untuk melakukan itu, tambahkan blok kod berikut ke dalam fail server.js anda:
...
sequelize.authenticate().then(() => {
console.log('Connection has been established successfully.');
}).catch((error) => {
console.error('Unable to connect to the database: ', error);
});Kaedah authenticate() digunakan untuk berhubung dengan pangkalan data dan menguji sama ada kelayakan yang diberikan adalah betul. Di sini, sambungan pangkalan data dibuka secara lalai dan sambungan yang sama boleh digunakan untuk semua pertanyaan. Apabila anda perlu menutup sambungan, panggil kaedah sequelize.close() selepas panggilan authenticate() ini. Untuk mengetahui lebih lanjut tentang Sequelize, sila lihat panduan permulaan mereka.
Kebanyakan kaedah yang disediakan oleh Sequelize adalah tidak serentak (asynchronous). Ini bermakna anda boleh menjalankan proses dalam aplikasi anda sementara blok kod tidak serentak sedang dijalankan. Selain itu, selepas blok kod tidak serentak berjaya dijalankan, ia akan memulangkan promise, iaitu nilai yang dikembalikan pada akhir sesuatu proses. Oleh itu, dalam blok kod tidak serentak, anda boleh menggunakan then(), catch(), dan finally() untuk mengembalikan data yang telah diproses.
Pada ketika ini, fail server.js akan kelihatan seperti berikut:
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);
});Simpan dan tutup fail anda.
Dalam direktori projek, jalankan aplikasi server.js dengan menjalankan arahan berikut:
node server.jsOutput anda akan kelihatan seperti ini:
Connection has been established successfully!Anda telah berjaya membuat sambungan pangkalan data.
Dalam langkah ini, anda telah memasang Sequelize, mencipta pangkalan data contoh, dan menggunakan Sequelize untuk berhubung dengan pangkalan data. Seterusnya, anda akan bekerja dengan model dalam Sequelize.
Membuat Jadual Pangkalan Data Menggunakan Sequelize
Sekarang bahawa anda telah mencipta pangkalan data MySQL contoh, anda boleh menggunakan Sequelize untuk mencipta jadual dan mengisinya dengan data. Dalam Sequelize, jadual pangkalan data dirujuk sebagai model. Model adalah abstraksi yang mewakili jadual dalam pangkalan data. Model mentakrifkan beberapa perkara kepada Sequelize, seperti nama jadual, butiran lajur, dan jenis data. Dalam langkah ini, anda akan mencipta model Sequelize untuk data buku.
Untuk memulakan, buat fail baru bernama book.model.js dalam direktori projek:
nano book.model.jsSerupa dengan langkah sebelumnya, tambah kod Sequelize untuk permulaan pangkalan data dengan import baru untuk DataTypes di bahagian atas fail:
const { Sequelize, DataTypes } = require("sequelize");Sequelize mengandungi banyak jenis data terbina dalam. Untuk mengakses jenis data tersebut, anda perlu menambah import untuk DataTypes. Tutorial ini merujuk kepada beberapa jenis data yang kerap digunakan, seperti STRING, INTEGER, dan DATEONLY. Untuk mengetahui lebih lanjut tentang jenis data lain yang disokong, anda boleh merujuk dokumentasi rasmi Sequelize.
Kemudian, sertakan baris yang anda gunakan sebelum ini untuk membuat sambungan ke pangkalan data MySQL anda, dengan mengemas kini kelayakan MySQL anda dengan sewajarnya:
...
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);
});Seterusnya, anda akan mencipta model yang dipanggil books, yang merangkumi title, author, release_date, dan ID subject. Untuk melakukannya, gunakan kaedah sequelize.define() seperti berikut:
...
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,
}
});Kaedah sequelize.define() mentakrifkan model baharu, yang mewakili jadual dalam pangkalan data. Blok kod ini mencipta satu jadual yang dipanggil books dan menyimpan rekod buku mengikut title, author, release_date, dan subject.
Dalam kod ini, allowNull menunjukkan bahawa nilai lajur model tidak boleh null. Begitu juga, jika anda perlu menetapkan nilai sedemikian, anda boleh menggunakan defaultValue: "value".
Seterusnya, anda akan menambah model book ke dalam pangkalan data anda. Untuk melakukannya, anda akan menggunakan kaedah sync() seperti berikut:
...
sequelize.sync().then(() => {
console.log('Book table created successfully!');
}).catch((error) => {
console.error('Unable to create table : ', error);
});Dalam kaedah sync(), anda meminta Sequelize untuk melakukan beberapa perkara ke atas pangkalan data. Dengan panggilan ini, Sequelize secara automatik akan menjalankan kueri SQL ke pangkalan data dan mencipta jadual, serta mencetak mesej Jadual Buku berjaya dicipta!.
Seperti yang disebutkan, kaedah sync() adalah kaedah berasaskan janji, yang bermaksud ia juga boleh melakukan pengendalian ralat. Dalam blok kod ini, anda akan memeriksa sama ada jadual berjaya dibuat. Jika tidak, ia akan mengembalikan ralat melalui kaedah catch dan mencetaknya pada output.
Nota: Anda boleh menguruskan penyegerakan model dengan menghantar parameter force untuk memaksa penciptaan jadual baru jika ia tidak wujud, atau sebaliknya gunakan yang sedia ada. Berikut adalah beberapa contoh, yang mungkin berguna untuk anda semasa bekerja dengan Sequelize:
model.sync(): Ini akan membuat jadual jika ia belum wujud.model.sync({ force: true }): Ini akan mencipta jadual dengan memadamnya jika jadual yang sama sudah wujud.
Kod akhir akan kelihatan seperti ini:
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);
});Simpan dan tutup fail anda.
Jalankan aplikasi anda dengan menggunakan arahan berikut:
node book.model.jsAnda akan mendapat output berikut dalam baris perintah anda:
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!Dalam output, anda akan melihat log pemulangan mengandungi mesej, Jadual buku berjaya dibuat!. Anda boleh mengesahkannya dengan memeriksa pangkalan data anda untuk melihat jadual books baru yang telah dibuat dalam pangkalan data hello_world_db.
Untuk mengesahkan penciptaan jadual baru, log masuk ke dalam instans MySQL anda:
mysql -u YOUR_USERNAME -pSelepas memasukkan kata laluan anda, bertukar ke pangkalan data contoh:
USE hello_world_db;Dan kemudian jalankan arahan untuk menunjukkan jadual:
SHOW TABLES;Keluaran anda akan serupa dengan ini:
+---------------------------+
| Tables_in_hello_world_db |
+---------------------------+
| books |
+---------------------------+
1 row in set (0.00 sec)Akhirnya, putuskan sambungan dari pelayan MySQL:
mysql> QUITAnda telah mengesahkan bahawa penciptaan model book berjaya. Dengan menggunakan proses ini, anda boleh mencipta bilangan model yang tidak terhad dengan mengikuti prosedur yang sama.
Dalam langkah ini, anda telah mencipta model dalam pangkalan data dan memulakan kerja dengan model menggunakan kaedah terbina dalam. Anda juga telah menggunakan jenis data yang disokong oleh Sequelize untuk mentakrifkan model anda. Seterusnya, anda akan bekerja dengan pertanyaan model asas.
Menggunakan Sequelize untuk Pertanyaan Pangkalan Data
Dalam langkah ini, anda akan menggunakan kueri terbina dalam Sequelize untuk penyisipan, pemilihan, pemilihan dengan klausa bersyarat, dan penghapusan.
Memasukkan Rekod Baru
Dalam langkah sebelumnya, anda telah mencipta model book di dalam pangkalan data. Dalam bahagian ini, anda akan memasukkan data ke dalam model ini.
Untuk memulakan, salin kandungan book.model.js dari langkah sebelumnya. Cipta fail baru yang dipanggil book.controller.js untuk mengendalikan logik pertanyaan. Tambahkan kod dari book.model.js ke book.controller.js.
Dalam book.controller.js, cari kaedah sync(). Dalam kaedah sync(), tambahkan baris yang disorot berikut:
...
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);
});Di sini, anda memasukkan rekod buku baru ke dalam model books yang telah anda buat menggunakan kaedah sync(), yang menyokong penambahan rekod baru ke model yang telah dibuat sebelumnya. Setelah kaedah sync() dijalankan dengan berjaya, ia akan menjalankan kaedah then(). Di dalam kaedah then(), anda memanggil kaedah create() untuk memasukkan rekod baru ke dalam model.
Anda menggunakan kaedah create() untuk menghantar data yang anda perlu tambah ke pangkalan data sebagai satu objek. Bahagian kod yang disorot akan memasukkan entri baru ke dalam jadual books sedia ada anda. Dalam contoh ini, anda menambah Clean Code oleh Robert Cecil Martin, yang telah dikategorikan dengan ID subject 3. Anda boleh menggunakan kod yang sama, yang dikemas kini dengan maklumat untuk buku lain, untuk menambah rekod baru ke pangkalan data anda.
Simpan dan tutup fail itu.
Jalankan aplikasi menggunakan arahan berikut:
node book.controller.jsKeluaran anda akan kelihatan seperti berikut:
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,
...
}Anda telah memasukkan rekod baru ke dalam model yang anda cipta dalam pangkalan data. Anda boleh terus menambah beberapa rekod menggunakan proses yang sama.
Memilih Semua Rekod
Dalam bahagian ini, anda akan memilih dan mendapatkan semua rekod buku dari pangkalan data menggunakan kaedah findAll(). Untuk melakukan itu, mulakan dengan membuka book.controller.js dan hapuskan kaedah Book.create() yang sebelumnya. Dalam kaedah sync(), tambahkan kaedah Book.findAll() seperti yang ditunjukkan:
...
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);
});
...Simpan dan tutup fail itu.
Seterusnya, jalankan aplikasi itu semula menggunakan arahan berikut:
node book.controller.jsKeluaran anda akan kelihatan seperti berikut:
[
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
},
...
]Keluaran mengandungi semua data buku sebagai objek array. Anda berjaya menggunakan kaedah Sequelize findAll() untuk mengembalikan semua data buku dari pangkalan data.
Memilih dengan Klausa where
Dalam bahagian ini, anda akan memilih nilai dengan syarat menggunakan klausa where. Klausa where digunakan untuk menentukan syarat semasa mendapatkan data. Untuk tutorial ini, anda akan mendapatkan sebuah buku berdasarkan ID rekod tertentu dari pangkalan data menggunakan kaedah findOne().
Untuk melakukan itu, buka book.controller.js untuk penyuntingan, padamkan kaedah findAll(), dan tambahkan baris berikut:
...
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);
});Di sini, anda memilih rekod buku tertentu dari pangkalan data menggunakan kaedah findOne() dengan pilihan where. Dalam contoh ini, anda sedang mendapatkan data buku yang id-nya sama dengan 1.
Simpan dan tutup fail itu.
Seterusnya, jalankan aplikasi:
node book.controller.jsKeluaran anda akan kelihatan seperti berikut:
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
},
...
}Anda telah berjaya menggunakan klausa where untuk mendapatkan data daripada model Sequelize. Anda boleh menggunakan klausa where dalam aplikasi pangkalan data untuk menangkap data bersyarat.
Memadam Rekod
Untuk memadam rekod tertentu daripada model pangkalan data, anda menggunakan kaedah destroy() dengan pilihan where. Untuk berbuat demikian, buka book.controller.js, buang kaedah findOne(), dan tambah baris yang disorot berikut:
...
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);
});Di sini, anda menghapus rekod buku dari pangkalan data dengan menggunakan kaedah destroy() bersama pilihan where dan memasukkan id buku yang ingin dihapus. Anda akan menghapus rekod buku yang id-nya sama dengan 2.
Simpan dan tutup fail itu.
Seterusnya, jalankan aplikasi:
node book.controller.jsKeluaran anda akan kelihatan seperti berikut:
Successfully deleted record.Rekod telah dipadam.
Dalam langkah ini, anda mencuba model pangkalan data anda dan pertanyaan model. Anda memulakan pangkalan data, mencipta model, memasukkan rekod, mendapatkan rekod, mendapatkan rekod dengan syarat menggunakan klausa where, dan memadam rekod yang terpilih. Dengan pengetahuan tentang Sequelize ini, anda kini akan mencipta perkaitan dalam Sequelize. Selepas itu, anda akan dapat mentakrif dan bekerja dengan pelbagai jenis hubungan menggunakan model Sequelize.
Mewujudkan Persatuan Menggunakan Sequelize
Dalam langkah ini, anda akan menggunakan jenis persatuan standard yang disokong oleh Sequelize: satu-ke-satu, satu-ke-banyak, dan banyak-ke-banyak. Anda akan menggunakan data contoh tentang pelajar, kursus, dan tahap gred.
Sequelize menggunakan jenis perkaitan berdasarkan hubungan pangkalan data berikut:
Hubungan satu-ke-satu: Hubungan satu-ke-satu bermaksud satu rekod dalam satu jadual dikaitkan dengan tepat satu rekod dalam jadual lain. Dari segi Sequelize, anda boleh menggunakan perkaitan
belongsTo()danhasOne()untuk mewujudkan jenis hubungan ini.Perhubungan satu-ke-banyak: Perhubungan satu-ke-banyak bermaksud satu rekod dalam satu jadual berkaitan dengan pelbagai rekod dalam jadual lain. Dengan Sequelize, anda boleh menggunakan kaedah persatuan
hasMany()untuk mewujudkan jenis perhubungan ini.Hubungan banyak-ke-banyak: Hubungan banyak-ke-banyak bermakna berbilang rekod dalam satu jadual dikaitkan dengan berbilang rekod dalam jadual lain. Dengan Sequelize, anda boleh menggunakan persatuan
belongsToMany()untuk mewujudkan jenis hubungan ini.
Sebelum membuat hubungan ini, anda akan terlebih dahulu membuat pangkalan data baru yang dipanggil student_db dan menambah model baru serta beberapa data contoh untuk pelajar, kursus, dan tahap gred.
Untuk membuat pangkalan data, ikut proses yang sama dalam Memasang dan Mengkonfigurasi Sequelize untuk log masuk ke MySQL dan membuat pangkalan data bernama student_db. Setelah pangkalan data baru dibuat, log keluar dari MySQL. Seterusnya, anda akan mula membuat hubungan pangkalan data.
Mewujudkan Hubungan Satu-ke-Satu dengan belongsTo()
Dalam bahagian ini, anda akan mencipta hubungan satu-ke-satu menggunakan model Sequelize. Bayangkan anda ingin mendapatkan maklumat seorang pelajar beserta tahap gred mereka. Oleh kerana seorang pelajar hanya boleh mempunyai satu tahap gred, jenis perkaitan ini adalah hubungan satu-ke-satu dan anda boleh menggunakan kaedah belongsTo().
Nota: Terdapat perbezaan antara belongsTo() dan hasOne(). belongsTo() akan menambah foreignKey pada jadual sumber, manakala hasOne() akan menambahkannya pada jadual sasaran. Dalam apa jua keadaan, jika kedua-dua hubungan digunakan pada masa yang sama, ia akan berfungsi sebagai hubungan satu-ke-satu dua hala dalam Sequelize.
Kaedah belongsTo() membolehkan anda membuat hubungan satu-ke-satu antara dua model Sequelize. Dalam contoh ini, anda menggunakan model Student dan Grade.
Buat fail baru yang dipanggil one_to_one.js. Seperti yang anda lakukan dalam bahagian sebelumnya, Menyambung ke Pangkalan Data MySQL, sertakan baris untuk membuat sambungan ke pangkalan data dan mengesahkan pengguna MySQL anda di bahagian atas fail. Pastikan untuk mengemas kini kelayakan MySQL mengikut keperluan:
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);
});Dalam bahagian ini, anda akan mencipta tiga model dalam pangkalan data baru student_db: Student, Grade, dan Course. Anda akan bermula dengan mencipta model Student dan Grade. Kemudian dalam langkah ini, anda akan mencipta model Courses.
Untuk model Student, tambahkan blok kod berikut ke 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
}
});Model pelajar ini mengandungi dua lajur: student_id dan name.
Seterusnya, tambahkan blok kod untuk Grade model:
...
const Grade = sequelize.define("grades", {
grade: {
type: DataTypes.INTEGER,
allowNull: false
}
});Model Grade mengandungi lajur grade.
Untuk menunjukkan hubungan tersebut, anda perlu menambah data contoh ke dalam pangkalan data. Untuk itu, anda akan menggunakan kaedah bulk(). Daripada memasukkan data satu per satu ke dalam baris, kaedah bulkCreate() membolehkan anda memasukkan beberapa baris ke dalam model pangkalan data anda sekaligus.
Jadi sekarang, import data Grade dan Student ke dalam model masing-masing dalam pangkalan data seperti yang ditunjukkan:
...
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);
});Di sini, anda menyediakan data contoh dan memasukkan data ke dalam model Student dan Grade. Dengan pangkalan data, model, dan data contoh anda siap, anda sedia untuk membuat kaitan.
Dalam one-to-one.js, tambah baris berikut di bawah blok student_data:
...
Student.belongsTo(Grade);Seterusnya, anda perlu memeriksa sama ada perkaitan berfungsi dengan betul. Untuk melakukan itu, anda boleh mengambil semua data pelajar beserta tahap gred yang berkaitan dengan menyerahkan parameter include dalam kaedah findAll().
Oleh kerana anda perlu mendapatkan tahap gred pelajar, anda akan menghantar Grade sebagai model. Dalam kaedah sequelize.sync(), tambah baris yang diserlahkan seperti yang ditunjukkan:
...
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);
});Kod lengkap kelihatan seperti berikut:
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);
});Simpan dan tutup fail anda.
Jalankan fail itu dengan menggunakan arahan berikut:
node one_to_one.jsKeluaran akan panjang, dan anda akan melihat semua data pelajar beserta tahap gred mereka. Berikut adalah petikan keluaran yang menunjukkan data pelajar:
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:
...Bergantung pada alat baris perintah yang anda gunakan, output mungkin dicetak sebagai paparan yang diperluas atau tidak. Jika ia adalah paparan yang diperluas, ia akan mencetak objek grade yang diperluas sebagai output.
Dalam bahagian ini, anda telah mencipta hubungan satu-ke-satu menggunakan panggilan kaedah Student.belongsTo(Grade); dan mendapat maklumat mengikut persatuan yang anda cipta.
Mewujudkan Hubungan Satu-ke-Banyak dengan hasMany()
Dalam bahagian ini, anda akan membuat hubungan satu-ke-banyak menggunakan model Sequelize. Bayangkan anda ingin mendapatkan semua pelajar yang dikaitkan dengan tahap gred yang dipilih. Oleh kerana satu tahap gred tertentu boleh mempunyai pelbagai pelajar, ini adalah hubungan satu-ke-banyak.
Untuk memulakan, salin kandungan one_to_one.js ke dalam fail baru yang dipanggil one_to_many.js. Dalam one_to_many.js, buang baris-baris selepas blok student_data. Fail one_to_many.js anda akan kelihatan seperti ini:
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}
]Selepas blok student_data, gunakan kaedah hasMany() untuk mencipta hubungan baru:
...
Grade.hasMany(Student)Kaedah hasMany() membolehkan anda membuat hubungan satu-ke-banyak antara dua model Sequelize. Di sini, anda menggunakan model Grade dan Student.
Seterusnya, tambahkan kaedah sequelize.sync() bersama kaedah findAll() di bawah baris 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);
});Di sini anda cuba mengakses semua pelajar dalam tahap gred tertentu—dalam kes ini, semua pelajar dalam gred 9. Anda juga menambah model Student dalam pilihan include.
Berikut adalah kod lengkap:
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);
});Simpan dan tutup fail anda.
Jalankan fail dengan arahan berikut:
node one_to_many.jsKeluaran akan kelihatan serupa dengan berikut. Ia akan agak panjang, tetapi semua pelajar dalam gred 9 akan dipaparkan seperti berikut:
[ 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 },
...Dalam bahagian ini, anda telah mencipta hubungan satu-ke-banyak menggunakan panggilan kaedah Grade.hasMany(Student);. Dalam output, anda telah mendapatkan butiran mengikut hubungan yang anda cipta.
Mewujudkan Hubungan Ramai-ke-Ramai dengan belongsToMany()
Dalam bahagian ini, anda akan mencipta hubungan banyak-ke-banyak menggunakan model Sequelize. Sebagai contoh, bayangkan situasi di mana pelajar mendaftar dalam kursus. Seorang pelajar boleh mendaftar dalam banyak kursus dan satu kursus boleh mempunyai ramai pelajar. Ini adalah hubungan banyak-ke-banyak. Untuk melaksanakan ini menggunakan Sequelize, anda akan menggunakan model Student, Course, dan StudentCourse dengan kaedah belongsToMany().
Untuk memulakan, buat fail bernama many_to_many.js dan tambah blok kod permulaan dan autentikasi pangkalan data seperti berikut. (Anda boleh menggunakan semula blok kod dari contoh one_to_many.js sebelum ini.) Pastikan untuk mengemas kini nilai sambungan pangkalan data yang diserlahkan mengikut keperluan.
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);
});Seterusnya, anda akan mencipta model pangkalan data untuk hubungan banyak-ke-banyak: Student dan Course. Kemudian anda akan menambah beberapa data contoh kepada model tersebut.
...
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},
]Di sini, anda mencipta model Student dan Course serta menyediakan beberapa data contoh. Anda juga menetapkan courseID, yang akan anda gunakan untuk mendapatkan pelajar mengikut jenis hubungan ini.
Akhirnya, anda mentakrifkan model baru yang dipanggil StudentCourse, yang menguruskan data hubungan antara Student dan Course. Dalam contoh ini, studentId 1 didaftarkan dalam courseId 1 dan courseId 2.
Anda telah menyelesaikan inisiasi pangkalan data dan menambah data contoh ke dalam pangkalan data. Seterusnya, wujudkan hubungan banyak-ke-banyak menggunakan kaedah belongsToMany() seperti yang ditunjukkan:
...
Course.belongsToMany(Student, { through: 'StudentCourse'})
Student.belongsToMany(Course, { through: 'StudentCourse'})Dalam kaedah belongsToMany(), anda menghantar konfigurasi through dengan nama model sebagai pilihan konfigurasi. Dalam kes ini, ia adalah StudentCourse. Ini adalah jadual yang menguruskan hubungan banyak-ke-banyak.
Akhirnya, anda boleh memeriksa sama ada perkaitan berfungsi dengan betul dengan mendapatkan semua data kursus bersama pelajar yang berkaitan. Anda akan melakukan itu dengan menggunakan parameter include di dalam kaedah findAll(). Tambahkan baris berikut ke 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);
});Kod lengkap kelihatan seperti berikut:
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);
});Simpan dan tutup fail itu.
Jalankan fail menggunakan arahan berikut:
node many_to_many.jsKeluaran akan panjang, tetapi akan kelihatan lebih kurang seperti berikut:
[ 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:
...Seperti yang anda boleh lihat dalam output ini, kursus yang mempunyai pelajar yang berkaitan telah diambil. Dalam blok courses, anda akan melihat nilai id yang berasingan yang menunjukkan setiap kursus. Sebagai contoh, id: 1 berkaitan dengan course_name: Science untuk kelas Sains, manakala id: 2 adalah kelas Matematik, dan seterusnya.
Dalam pangkalan data, anda boleh melihat tiga jadual yang dijana dengan data contoh yang anda masukkan.
Dalam langkah ini, anda menggunakan Sequelize untuk membuat hubungan satu-ke-satu, satu-ke-banyak, dan banyak-ke-banyak. Seterusnya, anda akan bekerja dengan pertanyaan mentah.
Bekerja dengan Pertanyaan Mentah
Dalam langkah ini, anda akan bekerja dengan pertanyaan mentah dalam Sequelize. Dalam langkah sebelumnya, anda menggunakan kaedah bawaan Sequelize, seperti insert() dan findAll(), untuk mengendalikan penyisipan data dan pemilihan dari pangkalan data. Anda mungkin telah perasan bahawa kaedah-kaedah tersebut mengikuti corak tertentu untuk menulis pertanyaan. Walau bagaimanapun, dengan penggunaan pertanyaan mentah, anda tidak perlu risau tentang kaedah dan corak bawaan Sequelize. Dengan menggunakan pengetahuan anda tentang pertanyaan SQL, anda boleh melaksanakan pelbagai pertanyaan dalam Sequelize dari yang mudah hingga yang lebih maju.
Berikut adalah contoh pertanyaan mentah yang melaksanakan tindakan memilih semua nilai dari jadual tertentu, memadam nilai yang dipilih mengikut syarat, dan mengemas kini jadual dengan nilai yang diberikan.
SELECT * FROM table_name;
DELETE FROM table_name WHERE condition;
UPDATE table_name SET y = 42 WHERE x = 12;Dalam Sequelize, kueri mentah boleh digunakan dengan dua metodologi utama: penggantian array dan penggantian objek. Apabila anda menghantar nilai kepada kueri SQL, anda boleh menggunakan sama ada array atau objek untuk melakukan penggantian itu.
Sebelum menulis pertanyaan mentah, anda perlu menyediakan data pelajar dalam pangkalan data contoh terlebih dahulu. Mengikut bahagian sebelum ini, Membuat Pangkalan Data Contoh, log masuk ke MySQL, buat pangkalan data yang dipanggil sample_student_db, dan log keluar dari MySQL.
Seterusnya, anda akan menambah beberapa data mentah untuk mula bekerja dengan pertanyaan mentah. Buat fail baru bernama add_student_records.js dan tambah blok kod berikut, yang mengandungi kaedah Sequelize yang telah dibincangkan sebelum ini iaitu authenticate(), sync(), dan 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);
});Di sini, anda memulakan sambungan pangkalan data, membuat model, dan memasukkan beberapa rekod pelajar ke dalam pangkalan data baru.
Simpan dan tutup fail itu.
Seterusnya, jalankan skrip ini menggunakan arahan berikut:
node add_student_records.jsKeluaran akan kelihatan serupa dengan berikut. Ia akan agak panjang, tetapi semua rekod pelajar yang anda masukkan akan dipaparkan seperti berikut. Perlu diingat bahawa kerana student_id adalah nilai UUID (Pengecam Unik Sejagat) yang dijana secara automatik, ia akan berbeza bergantung pada pengguna.
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
},
…Dalam bahagian seterusnya, anda akan menggunakan pertanyaan mentah dengan salah satu output student_id dalam blok kod di atas. Salinnya supaya anda mempunyainya untuk bahagian seterusnya, di mana anda akan menggunakan kaedah query() untuk penggantian array dan objek.
Penggantian Susunan
Dalam bahagian ini, anda akan menggunakan kaedah query() untuk penggantian susunan. Dengan kaedah ini, Sequelize boleh melaksanakan kueri SQL mentah atau yang telah disediakan.
Untuk memulakan, salin kandungan fail server.js dari Langkah 1, kerana itu termasuk kaedah Sequelize() untuk memulakan dan inisiasi pangkalan data. Tampal kandungan tersebut ke dalam fail baru bernama array_raw_query.js. Kemas kini nama pangkalan data kepada 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);
});Di akhir fail, tambah blok kod berikut untuk penggantian array, pastikan untuk menggantikan REPLACE_STUDENT_ID dengan nilai student_id yang anda salin dalam bahagian sebelumnya.
...
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);
});Untuk penggantian array, anda menghantar kaedah query() dengan pertanyaan SQL dan objek konfigurasi. Ia mengandungi nilai dan jenis replacements. Untuk penggantian, anda menghantar data sebagai array dan menangkap nilai-nilai tersebut menggunakan simbol tanda soal (?).
Seterusnya, kerana anda perlu mendapatkan data tentang seorang pelajar tertentu, student_id dihantar sebagai parameter kedua. Selepas itu, anda menghantar pasangan kunci-nilai type: sequelize.QueryTypes.SELECT, yang boleh anda gunakan untuk memilih data dari pangkalan data.
Terdapat beberapa jenis lain juga, seperti QueryTypes.UPDATE dan QueryTypes.DELETE. Bergantung pada keperluan, anda boleh memilih jenis yang sesuai dengan tujuan anda.
Berikut menunjukkan blok kod penuh. Di sini anda menyambung ke pangkalan data dan mengambil data pelajar yang dipilih menggunakan pertanyaan mentah.
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);
});Simpan dan tutup fail anda.
Seterusnya, anda boleh menjalankan skrip ini menggunakan arahan berikut:
node array_raw_query.jsAnda akan melihat output yang serupa dengan berikut:
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 } ]Disebabkan oleh student_id yang dipilih, nilai output anda mungkin berbeza.
Penggantian Objek
Pada permukaan, penggantian objek adalah serupa dengan penggantian tatasusunan, tetapi corak pemindahan data ke kueri mentah adalah berbeza. Dalam pilihan penggantian, anda menghantar data sebagai objek, dan dalam pilihan kueri, anda menggunakan nilai seperti :key.
Untuk memulakan, buat fail baru bernama object_raw_query.js dan tampal keseluruhan blok kod dari fail server.js, sambil mengemas kini pangkalan data kepada 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);
});Kemudian, tambah blok kod berikut di hujung fail object_raw_query.js yang baru:
...
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);
});Di sini, anda mendapatkan data pelajar yang dipilih menggunakan kaedah penggantian objek. Anda mencipta objek replacement, menetapkan id sebagai maklumat pelajar yang ingin anda ambil: { id: '<mark>GANTI_ID_PELAJAR</mark>' }.
Dalam query(), anda menyatakan: 'SELECT * FROM students WHERE student_id=:id'. Menggunakan kaedah query(), anda menghantar nilai gantian sebagai objek, sebab itulah kaedah ini dikenali sebagai penggantian objek.
Berikut adalah kod lengkap:
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);
});Simpan dan tutup fail itu.
Seterusnya, jalankan skrip ini menggunakan arahan berikut:
node object_raw_query.jsKeluaran akan kelihatan serupa dengan yang berikut:
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 } ]Disebabkan student_id yang dipilih, nilai output anda mungkin berbeza.
Dalam langkah ini, anda bekerja dengan kueri mentah Sequelize menggunakan dua metodologi berbeza: penggantian array dan penggantian objek.
Menetapkan Pembolehubah Persekitaran untuk Sambungan Pangkalan Data yang Selamat
Sehingga ke peringkat ini, anda telah menyimpan kelayakan pangkalan data terus dalam kod anda. Walaupun pendekatan ini berkesan untuk percubaan secara tempatan, ia tidak selamat. Menyimpan kelayakan secara keras mendedahkan maklumat sensitif seperti kata laluan pangkalan data dan nama hos, serta meningkatkan risiko pencerobohan apabila kod dikongsi atau digunakan. Dalam bahagian ini, anda akan belajar bagaimana untuk menyimpan kelayakan ini dengan selamat menggunakan pembolehubah persekitaran.
Mengapa Menggunakan Pemboleh Ubah Persekitaran?
Pembolehubah persekitaran bertindak sebagai parameter konfigurasi luaran yang boleh dibaca oleh aplikasi anda semasa runtime. Daripada menyelitkan kelayakan secara terus dalam kod anda, ia disimpan dalam sistem anda atau dalam fail konfigurasi berasingan yang tidak pernah dimasukkan ke dalam kawalan versi. Pendekatan ini memberikan pelbagai manfaat:
- Keselamatan: Maklumat kelayakan anda tetap tersembunyi daripada repositori awam dan sistem kawalan versi.
- Fleksibiliti: Setiap persekitaran (pembangunan, persediaan, pengeluaran) boleh menggunakan konfigurasi pangkalan data yang berbeza tanpa mengubah kod sumber.
- Penyelenggaraan: Konfigurasi berpusat membolehkan kemas kini dengan mudah, jika kata laluan pangkalan data berubah, anda hanya perlu mengubah satu fail atau pembolehubah sahaja.
- Pematuhan: Amalan ini selaras dengan metodologi Aplikasi Dua Belas Faktor, yang menggalakkan pengurusan konfigurasi khusus persekitaran untuk aplikasi yang boleh diskala.
Menetapkan Pembolehubah Persekitaran
Anda akan menggunakan pakej dotenv untuk menguruskan pembolehubah persekitaran anda dalam Node.js. Pustaka ini membaca pembolehubah dari fail .env dan menyuntikkannya ke dalam objek process.env Node.js, menjadikannya boleh diakses di seluruh aplikasi anda.
Pasang pakej dotenv dengan menjalankan arahan berikut:
npm install dotenvSelepas memasang, buat fail baru bernama .env di direktori akar projek anda. Fail ini akan menyimpan semua data sensitif yang diperlukan untuk sambungan pangkalan data.
Berikut adalah contoh konfigurasi fail .env untuk tetapan Sequelize anda:
DB_NAME=hello_world_db
DB_USER=your_username
DB_PASSWORD=your_password
DB_HOST=localhost
DB_DIALECT=mysqlSetiap pembolehubah sepadan dengan parameter tertentu yang digunakan oleh Sequelize untuk mewujudkan sambungan.
Menyelamatkan Fail .env
Adalah penting supaya fail .env anda tidak pernah muncul dalam kawalan versi. Untuk mengelakkan ini, tambahkan ia ke dalam fail .gitignore anda supaya Git mengabaikannya semasa melakukan commit perubahan:
.envDalam persekitaran pengeluaran, pembolehubah persekitaran biasanya dikonfigurasikan terus dalam tetapan platform hos anda atau pengurus rahsia daripada fail .env tempatan.
Mengemas Kini Konfigurasi Sequelize Anda
Kini anda telah menetapkan pembolehubah persekitaran, kemas kini inisialisasi Sequelize anda untuk menggunakannya. Mulakan dengan mengimport dan mengkonfigurasi dotenv di bahagian atas fail pelayan utama anda (contohnya, 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);
});- Baris
require('dotenv').config()memuatkan semua pembolehubah yang ditakrifkan dalam fail.envke dalamprocess.env. - Sequelize membaca pembolehubah persekitaran semasa memulakan contoh baru.
- Ini memastikan tiada maklumat sensitif seperti nama pengguna atau kata laluan muncul dalam kod anda.
Pendekatan ini meningkatkan keselamatan dan membolehkan persekitaran yang berbeza menggunakan konfigurasi unik hanya dengan menukar nilai pemboleh ubah persekitaran.
Mengesahkan Konfigurasi
Setelah anda mengemas kini konfigurasi anda, anda boleh mengesahkan sambungan dengan menjalankan aplikasi Node.js anda:
node server.jsJika fail .env anda disediakan dengan betul dan pelayan MySQL sedang berjalan, anda akan melihat output berikut:
Connection has been established successfully.Jika berlaku ralat, semak semula bahawa:
- Kelayakan dalam fail
.envanda sepadan dengan yang terdapat dalam contoh MySQL anda. - Pelayan MySQL sedang berjalan dan boleh diakses dari hos anda.
- Fail
.envterletak di akar projek anda dan diformat dengan betul.
Amalan Terbaik untuk Konfigurasi Selamat
Menggunakan pembolehubah persekitaran adalah langkah pertama yang kukuh ke arah pengurusan konfigurasi yang selamat. Untuk memastikan keselamatan dan kebolehpercayaan yang berterusan, pertimbangkan amalan terbaik tambahan berikut:
- Gunakan konfigurasi berasingan bagi setiap persekitaran: Kekalkan fail
.envyang berbeza untukdevelopment,staging, danproduction. Anda boleh menamakan mereka sebagai.env.development,.env.staging, dan.env.production. - Memanfaatkan pengurus rahsia: Untuk persekitaran produksi, gunakan pengurus rahsia dan bukannya menyimpan rahsia dalam fail.
- Sahkan pembolehubah persekitaran: Gunakan utiliti konfigurasi atau skrip permulaan yang memeriksa sama ada pembolehubah diperlukan telah ditetapkan sebelum aplikasi dijalankan. Ini membantu mengelakkan ralat semasa menjalankan aplikasi.
- Tukar kelayakan secara berkala: Kemas kini kelayakan pangkalan data secara berkala untuk mengurangkan kesan kebocoran yang berpotensi.
- Hadkan akses pangkalan data: Konfigurasikan peranan pengguna pangkalan data supaya mempunyai keistimewaan paling minimum yang diperlukan untuk aplikasi.
Dengan melaksanakan pembolehubah persekitaran dan mengikuti amalan ini, anda memastikan bahawa aplikasi Sequelize anda mengekalkan kedua-dua fleksibiliti dan keselamatan dalam persekitaran pembangunan dan pengeluaran.
Amalan Terbaik untuk Migrasi dan Penyelarasan
Apabila mengembangkan skema pangkalan data, anda mempunyai dua pendekatan utama dengan Sequelize: menulis dan menjalankan migrasi secara eksplisit, atau menggunakan sequelize.sync() untuk membenarkan Sequelize menjana perubahan skema secara automatik. Kedua-dua pendekatan adalah sah, tetapi mereka mempunyai tujuan yang berbeza dan datang dengan pertukaran tertentu. Mari kita fahami bila untuk menggunakan setiap satu, cara menulis migrasi yang selamat, dan bagaimana menjalankannya dengan boleh dipercayai dalam pembangunan dan pengeluaran.
Migrasi vs sequelize.sync() — bila menggunakan yang mana
Migrasi (disyorkan untuk pengeluaran): Migrasi adalah perubahan berturutan dan versi pada skema anda. Ia disimpan dalam kawalan sumber, disemak melalui kod, dan dilaksanakan sebagai sebahagian daripada proses penyebaran anda. Gunakan migrasi dalam pengeluaran untuk sebarang perubahan skema yang menjejaskan integriti atau ketersediaan data.
sequelize.sync()(gunakan hanya untuk pembangunan dan prototaip):sync()sesuai untuk pembangunan tempatan, ujian, dan prototaip cepat kerana ia boleh mencipta atau menyesuaikan jadual secara automatik. Walau bagaimanapun, jangan gunakansync({ force: true })atausync({ alter: true })dalam pengeluaran: pilihan ini boleh memadam data atau membuat perubahan yang tidak selamat tanpa laluan rollback yang terkawal.
Alat: sequelize-cli dan pelari migrasi
CLI rasmi, sequelize-cli, adalah cara termudah untuk mengurus migrasi dengan Sequelize. Bagi pasukan yang memerlukan kawalan lebih atau aliran kerja khusus, umzug adalah alternatif popular.
Untuk memasang dan memulakan CLI dalam projek anda, jalankan:
npm install --save-dev sequelize-cli
npx sequelize-cli initIni akan membuat folder berikut:
config/ # Stores database configuration files
models/ # Stores your Sequelize model definitions
migrations/ # Stores migration files
seeders/ # Stores seeder files for inserting initial dataAnda perlu menambah folder-folder ini ke kawalan versi (kecuali sebarang fail yang mengandungi kelayakan). Ini memastikan setiap persekitaran menjalankan perubahan pangkalan data yang sama secara konsisten.
Membuat dan Menjalankan Migrasi
Untuk membuat fail migrasi baru, gunakan arahan berikut:
npx sequelize-cli migration:generate --name add-isbn-to-booksIni akan mencipta fail berpenanda masa di dalam folder migrations/. Buka fail tersebut dan tentukan apa yang harus berlaku apabila anda menerapkan migrasi (up) dan bagaimana untuk membalikannya (down):
module.exports = {
async up(queryInterface, Sequelize) {
await queryInterface.addColumn('books', 'isbn', {
type: Sequelize.STRING
});
},
async down(queryInterface) {
await queryInterface.removeColumn('books', 'isbn');
}
};- Fungsi
upmelaksanakan migrasi (menambah lajur). - Fungsi
downmembalikkan perubahan (menghapuskan lajur).
Jalankan migrasi menggunakan:
npx sequelize-cli db:migrateUntuk membalikkan migrasi terakhir, gunakan:
npx sequelize-cli db:migrate:undoAnda juga boleh membatalkan semua migrasi dalam pembangunan dengan menjalankan:
npx sequelize-cli db:migrate:undo:allMenulis migrasi selamat dan idempoten
Ikuti peraturan ini apabila menulis migrasi:
Balut operasi dalam transaksi apabila disokong oleh pangkalan data. Ini memastikan migrasi sama ada berjaya sepenuhnya atau kembali sepenuhnya sekiranya berlaku ralat.
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 }); }); } };Pastikan migrasi kecil dan fokus. Setiap migrasi harus melakukan satu perubahan logik sahaja (menambah lajur, mencipta indeks, menamakan semula lajur). Migrasi yang lebih kecil lebih mudah untuk dikaji, diuji, dan dikembalikan.
Bersikap defensif dan idempoten. Apabila sesuai, semak kewujudan untuk mengelakkan kegagalan dalam persekitaran yang mengalami perubahan. Gunakan
queryInterface.describeTable()atau kueri mentah untuk melindungi operasi.Elakkan operasi pemusnahan dalam satu langkah. Sebagai contoh, untuk membuang lajur dengan selamat, tambahkan lajur baru, isi data di dalamnya, alihkan bacaan kepada lajur baru dalam kod aplikasi, dan hanya kemudian buang lajur lama dalam migrasi seterusnya.
Migrasi jangka panjang dan tanpa henti
Jadual besar dan operasi indeks boleh menyebabkan kunci. Gunakan strategi ini untuk meminimumkan kesan:
- Tambah lajur boleh kosong terlebih dahulu. Menambah lajur boleh kosong biasanya cepat. Elakkan menambah lajur dengan nilai lalai yang kompleks yang boleh mencetuskan penulisan semula seluruh jadual.
- Isi semula dalam jumlah kecil. Laksanakan tugas latar belakang untuk mengisi lajur baru secara berperingkat daripada menjalankan
UPDATEbesar sekaligus. - Cipta indeks tanpa kunci eksklusif jika boleh. Gunakan ciri khusus pangkalan data (contohnya, Postgres
CONCURRENTLYdan MySQL online DDL terkini) melalui SQL mentah dalam migrasi. - Pelaksanaan ciri-flag. Gunakan kod aplikasi yang membaca lajur baru di sebalik ciri-flag. Selepas pengisian semula selesai dan ujian lulus, tukar flag itu dan kemudian buang medan lama.
Pemulihan dan pembaikan kecemasan
- Sediakan migrasi
down. Setiapupharus mempunyaidownsebaliknya yang mendokumentasikan cara untuk membalikkan perubahan. Walaupun anda jarang menjalankandowndalam produksi, ia berfungsi sebagai pelan rollback yang jelas. - Rancang untuk pemulangan kecemasan. Jika migrasi menyebabkan masalah, bersedia untuk memulangkan kod aplikasi terlebih dahulu dan memulihkan pangkalan data daripada sandaran jika perlu. Uji prosedur pemulihan secara berkala.
Menanam data dan perubahan skema
- Kekalkan jumlah seeders minima dan stabil. Gunakan seeders untuk baris rujukan atau konfigurasi yang penting. Elakkan menyemai jumlah besar data perniagaan melalui migrasi.
- Pisahkan biji benih daripada migrasi struktur. Jika anda perlu mengisi data yang bergantung pada perubahan skema, lebih baik gunakan seeder susulan supaya tanggungjawab tetap jelas.
CI, semakan kod, dan automasi penyebaran
Jalankan migrasi di CI dan staging terlebih dahulu. Tambahkan langkah CI yang menjalankan migrasi terhadap pangkalan data sementara untuk menangkap kesilapan lebih awal.
Layan migrasi seperti kod. Periksa dan semak fail migrasi dalam permintaan tarik. Sertakan pemeriksaan automatik jika boleh.
Automatiskan pelaksanaan migrasi semasa penyebaran. Pastikan migrasi dijalankan sebelum proses aplikasi menerima trafik. Contoh skrip
package.json:"scripts": { "migrate": "npx sequelize-cli db:migrate", "start": "node server.js", "deploy": "npm run migrate && npm run start" }
Dalam penyebaran berasaskan bekas, jalankan migrasi sebagai kontena inisiasi atau dalam cangkuk penyebaran supaya proses web hanya bermula setelah migrasi selesai.
Menguji migrasi
- Uji kedua-dua arah. Jalankan
db:migratekemudiandb:migrate:undo:allsecara tempatan dan dalam CI untuk mengesahkan bahawaupdandownkedua-duanya berfungsi. - Gunakan pangkalan data boleh buang untuk ujian. Utamakan pangkalan data sementara atau bekas untuk larian ujian yang deterministik.
Mengikuti amalan terbaik ini memastikan migrasi Sequelize anda tetap boleh dipercayai, boleh dikesan, dan selamat untuk projek jangka panjang.
Tips Menyelesaikan Masalah dan Prestasi
Walaupun dengan persediaan yang kukuh, aplikasi Sequelize kadangkala boleh menghadapi masalah yang tidak dijangka seperti ralat sambungan pangkalan data, kegagalan migrasi, pertanyaan yang berjalan perlahan, kebuntuan, atau konflik keserentakan. Bahagian ini menyediakan panduan langkah demi langkah untuk mengenal pasti dan membaiki masalah ini, berserta amalan terbaik prestasi yang membantu memastikan aplikasi anda stabil dan efisien.
Penyelesaian Masalah Biasa
1. Ralat Sambungan
Masalah: Sequelize tidak dapat menyambung ke pangkalan data MySQL dan memunculkan ralat seperti SequelizeConnectionError: connect ECONNREFUSED, Access denied for user, atau SequelizeHostNotFoundError.
Cara Membetulkan:
Mulakan dengan mengesahkan bahawa butiran sambungan anda adalah betul. Semak semula nilai dalam fail .env anda, termasuk nama pangkalan data, nama pengguna, kata laluan, hos, dan port. Walaupun kesilapan kecil atau ruang kosong di hujung boleh menyebabkan Sequelize gagal untuk menyambung.
Seterusnya, pastikan pelayan MySQL anda sedang berjalan dan mendengar pada port lalai (3306). Anda boleh menguji sambungan dengan log masuk secara manual:
mysql -u your_username -p -h your_host -P 3306Jika arahan ini gagal, kemungkinan masalah terletak pada perkhidmatan MySQL atau kelayakan anda.
Jika anda menggunakan pakej dotenv, pastikan require('dotenv').config() muncul sebelum Sequelize diinisialisasi. Langkah ini memastikan semua pembolehubah persekitaran tersedia semasa runtime.
Akhir sekali, untuk sambungan jauh, sahkan tetapan firewall atau peraturan kumpulan keselamatan anda. Pelayan MySQL mesti menerima sambungan masuk dari hos aplikasi anda.
2. Kegagalan Migrasi
Masalah: Anda menjalankan npx sequelize-cli db:migrate atau sequelize.sync() dan menghadapi ralat seperti jadual yang hilang, lajur berganda, atau ketidakcocokan skema.
Cara Membetulkan:
Isu migrasi biasanya berlaku apabila fail dijalankan dalam susunan yang salah atau mengandungi ralat dalam operasi SQL. Sequelize memproses migrasi berdasarkan cap masa dalam nama fail, jadi pastikan bahawa fail tersebut dinamakan dengan betul.
Jika migrasi gagal, periksa mesej ralat dengan terperinci. Kemudian, kembalikan migrasi terakhir dengan selamat menggunakan:
npx sequelize-cli db:migrate:undoSelepas membetulkan fail migrasi, jalankan semula.
Sentiasa bungkus logik migrasi anda di dalam transaksi untuk memastikan atomik: sama ada semua perubahan berjaya atau tiada satu pun yang berjaya. Sebelum menjalankan migrasi di produksi, uji mereka dengan teliti pada pangkalan data staging atau tempatan untuk mengesahkan ketepatan.
3. Isu Penyelarasan Model
Masalah: Model Sequelize dan skema pangkalan data anda tidak sepadan, menyebabkan lajur hilang, jenis data salah, atau jadual yang sudah lapuk.
Cara Membetulkan:
Elakkan menggunakan sequelize.sync({ force: true }) dalam persekitaran pengeluaran, kerana ia akan memadam dan mencipta semula jadual, menyebabkan kehilangan data yang tidak dapat dipulihkan. Begitu juga, gunakan sequelize.sync({ alter: true }) dengan berhati-hati; ia mungkin mengubah skema secara tidak dijangka.
Sebaliknya, pilih migrasi yang jelas yang memperincikan setiap perubahan skema. Untuk membandingkan model anda dengan struktur pangkalan data sebenar, gunakan:
await queryInterface.describeTable('tableName');Ini membantu mengenal pasti ketidakpadanan sebelum ia menjejaskan pengeluaran.
4. Ralat Pertanyaan dan Masa Tamat
Masalah: Anda melihat ralat berkaitan masa tamat seperti Connection timeout atau Too many connections.
Cara Membetulkan:
Masalah tamat masa sering disebabkan oleh kolam sambungan yang habis atau sambungan yang tidak ditutup. Pastikan semua pertanyaan Sequelize ditunggu dengan betul supaya sambungan dikembalikan ke kolam selepas digunakan.
Anda juga boleh menyesuaikan konfigurasi kolam Sequelize untuk lebih sesuai dengan beban kerja aplikasi anda:
const sequelize = new Sequelize(DB_NAME, DB_USER, DB_PASSWORD, {
host: DB_HOST,
dialect: 'mysql',
pool: {
max: 10,
min: 0,
acquire: 30000,
idle: 10000
}
});Jika aplikasi anda mengendalikan banyak pengguna serentak, pertimbangkan untuk meningkatkan parameter max_connections MySQL dalam konfigurasi pangkalan data anda. Pantau sambungan aktif menggunakan SHOW PROCESSLIST; dalam MySQL untuk mengesan kebocoran atau sesi yang tidak digunakan.
5. Prestasi Pertanyaan Perlahan
Masalah: Sesetengah pertanyaan mengambil masa yang lebih lama daripada jangkaan, menyebabkan maklum balas API perlahan atau kelewatan tinggi.
Cara Mendiagnosis:
Mulakan dengan mengenal pasti pertanyaan yang lambat. Anda boleh merekod semua pertanyaan yang dijalankan oleh Sequelize dengan mengaktifkan log secara sementara:
const sequelize = new Sequelize(..., { logging: console.log });Kemudian, gunakan pernyataan EXPLAIN MySQL untuk memahami bagaimana pangkalan data melaksanakan pertanyaan itu:
EXPLAIN SELECT * FROM users WHERE email = 'user@example.com';Jika output menunjukkan "full table scan", pertanyaan itu tiada indeks.
Anda juga boleh mengaktifkan log pertanyaan perlahan MySQL untuk menangkap operasi perlahan secara automatik:
SET GLOBAL slow_query_log = 'ON';
SET GLOBAL long_query_time = 1;Cara Membetulkan:
Tambah indeks pada lajur yang kerap ditanya (terutamanya yang digunakan dalam klausa WHERE, JOIN, dan ORDER BY). Elakkan SELECT *, sebaliknya, ambil hanya medan yang anda perlukan dengan menggunakan pilihan attributes.
Jika Sequelize menghasilkan pertanyaan yang tidak efisien dengan gabungan yang tidak perlu, tulis semula pertanyaan itu menggunakan SQL mentah. Untuk laporan besar atau pertanyaan analitik, pecahkan mereka kepada langkah-langkah yang lebih kecil atau gunakan alat penimbal seperti Redis untuk menyimpan hasil yang berulang.
6. Deadlock dan Ralat Keserentakan
Masalah: Anda menerima ralat seperti Deadlock found when trying to get lock; try restarting transaction, terutamanya apabila beban tinggi.
Cara Mendiagnosis:
Semak status InnoDB dalam MySQL untuk mengenal pasti kueri atau jadual yang terlibat:
SHOW ENGINE INNODB STATUS\GKeluaran ini termasuk maklumat terperinci mengenai kebuntuan dan menunggu kunci yang berlaku baru-baru ini. Anda juga boleh mengaktifkan log umum atau log transaksi untuk melihat urutan pertanyaan yang membawa kepada isu tersebut.
Cara Membetulkan:
Deadlock berlaku apabila dua atau lebih transaksi saling menunggu kunci antara satu sama lain. Untuk meminimumkannya:
Pastikan transaksi sependek mungkin. Jangan panggil perkhidmatan luaran atau lakukan pengiraan berat semasa memegang kunci.
Sentiasa mengakses jadual dan baris dalam urutan yang sama merentasi transaksi untuk mengelakkan menunggu secara bulat.
Untuk kebuntuan berulang, laksanakan mekanisme percubaan semula yang mudah dengan penangguhan eksponen:
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; } } }Gunakan kunci aras-baris (
SELECT ... FOR UPDATE) hanya apabila perlu, dan lepaskan dengan segera.Bahagikan transaksi besar kepada beberapa batch kecil untuk mengurangkan pertindihan.
Laraskan tahap pengasingan transaksi jika sesuai, tetapi hanya selepas mengesahkan ia tidak akan menjejaskan konsistensi data.
Tips Pengoptimuman Prestasi
Masalah prestasi sering berpunca daripada pertanyaan yang tidak efisien, indeks yang hilang, atau pengurusan sambungan yang lemah. Berikut adalah beberapa petua praktikal untuk meningkatkan prestasi Sequelize tanpa mengorbankan kejelasan atau kebolehselenggaraan.
1. Mengoptimumkan Pertanyaan
Tulis pertanyaan yang meminta hanya apa yang diperlukan. Mengambil data yang tidak perlu meningkatkan penggunaan memori dan memperlahankan respons. Gunakan attributes untuk mengehadkan medan:
const users = await User.findAll({ attributes: ['id', 'name'] });Sentiasa tapis keputusan menggunakan lajur berindeks dan elakkan carian meluas seperti LIKE '%term%' jika boleh.
2. Gunakan Indeks dengan Berkesan
Indeks menjadikan carian lebih cepat tetapi boleh melambatkan penulisan. Tambah indeks hanya di tempat di mana ia memberikan manfaat yang ketara. Analisis prestasi pertanyaan dengan EXPLAIN MySQL untuk mengesahkan peningkatan sebelum dan selepas menambah indeks:
await queryInterface.addIndex('users', ['email']);3. Laraskan Kolam Sambungan
Kolam sambungan menentukan berapa banyak sambungan pangkalan data yang dikekalkan oleh Sequelize.
- Bagi aplikasi kecil, 5–10 sambungan biasanya mencukupi.
- Untuk sistem beban tinggi, tingkatkan saiz kumpulan dan laraskan masa tamat untuk mengelakkan kesesakan sambungan. Pantau penggunaan secara berkala menggunakan MySQL
SHOW PROCESSLIST;.
4. Aktifkan Pencatatan dan Pemantauan
Hidupkan log Sequelize sementara untuk meninjau pertanyaan SQL. Gunakan log pertanyaan perlahan MySQL untuk mengenal pasti pertanyaan yang melebihi had prestasi anda. Untuk pemantauan masa nyata, gabungkan alat pemantauan seperti PM2, New Relic, atau Datadog untuk mengukur kelewatan dan penggunaan sumber.
5. Cache Pertanyaan Kerap
Simpan hasil cache untuk data yang jarang berubah. Alat seperti Redis atau Memcached mengurangkan jumlah akses ke pangkalan data dan meningkatkan masa tindak balas, terutamanya untuk beban kerja yang banyak bacaan.
6. Hantar Nombor Halaman bagi Keputusan
Set keputusan yang besar menggunakan memori yang banyak. Sentiasa gunakan pagination untuk pertanyaan dalam API:
const users = await User.findAll({ limit: 50, offset: 100 });Paginasi memastikan respons ringan dan konsisten ketika beban tinggi.
7. Gunakan Pertanyaan Mentah untuk Operasi Kompleks
Jika abstraksi Sequelize menghasilkan SQL yang tidak cekap untuk kes penggunaan tertentu, jalankan pertanyaan SQL mentah secara langsung:
const [results] = await sequelize.query('SELECT name FROM users WHERE active = 1');Gunakan pertanyaan mentah dengan berhati-hati dan dokumentasikannya dengan jelas untuk penyelenggaraan di masa hadapan.
Soalan Lazim
1. Apa itu Sequelize dalam Node.js?
Sequelize adalah pemetaan objek-relasional (ORM) untuk Node.js yang menyediakan API berasaskan JavaScript tahap tinggi untuk bekerja dengan pangkalan data SQL seperti MySQL, PostgreSQL, SQLite, dan MariaDB. Daripada menulis SQL mentah untuk setiap operasi, anda menentukan model yang dipetak ke jadual pangkalan data dan menggunakan kaedah model untuk memasukkan, menanya, mengemas kini, dan memadam rekod. Sequelize juga menyokong hubungan (relasi antara model), transaksi, migrasi, dan pertanyaan mentah apabila anda memerlukan SQL secara langsung.
2. Bagaimana saya menyambungkan Sequelize ke MySQL?
Untuk menyambungkan Sequelize ke MySQL, anda perlu membuat instans Sequelize dengan kelayakan dan pilihan pangkalan data anda. Dalam fail Node.js, import Sequelize, secara pilihan muatkan pembolehubah persekitaran, kemudian cipta instansinya dengan nama pangkalan data, nama pengguna, kata laluan dan pilihan hos/dialek. Sebagai contoh:
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!');Sentiasa simpan kelayakan di luar kawalan sumber (contohnya, dalam fail .env atau pengurus rahsia).
3. Bagaimana saya membuat dan menyegerakkan model dalam Sequelize?
Dalam Sequelize, model mewakili jadual. Anda mendefinisikannya menggunakan sequelize.define() atau dengan melanjutkan kelas Model. Selepas itu, anda boleh menyegerakkan mereka dengan pangkalan data anda supaya Sequelize secara automatik mencipta jadual (bagus untuk pembangunan). Berikut adalah contoh kecil:
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();Untuk persekitaran pengeluaran, adalah lebih baik menggunakan migrasi supaya anda mempunyai kawalan versi ke atas perubahan skema.
4. Bagaimana saya menggunakan Sequelize dengan Express?
Dalam aplikasi Express, inisialisasikan Sequelize dalam fail berasingan (seperti db.js), eksport instans dan model yang bersambung, dan import mereka di mana sahaja anda memerlukannya dalam pengendali laluan atau pengawal anda. Gunakan async/await dalam pengendali laluan untuk memanggil kaedah model Sequelize, dan tangani ralat dengan try/catch atau middleware ralat. Berikut ialah bagaimana ia kelihatan dalam praktik:
// 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);
});Pastikan anda menjalankan migrasi atau memanggil sequelize.sync() sebelum memulakan server Express anda supaya jadual pangkalan data wujud apabila permintaan diterima.
5. Apakah perbezaan antara Sequelize dan pertanyaan SQL mentah?
Sequelize membolehkan anda menulis logik pangkalan data dalam JavaScript, manakala SQL mentah bermaksud menulis pernyataan SQL secara langsung. Sequelize menjadikan kod anda lebih kemas dan mudah diselenggara kerana anda boleh mentakrifkan model dan hubungan sekali sahaja dan menggunakannya di seluruh aplikasi anda. SQL mentah memberi anda lebih kawalan dan kadang-kadang boleh menjadi lebih pantas untuk pertanyaan yang sangat kompleks.
Ringkasnya, gunakan Sequelize untuk kebanyakan tugasan harian, dan gunakan SQL mentah apabila anda perlu memperhalusi prestasi atau menjalankan sesuatu yang sukar dinyatakan oleh Sequelize.
6. Bagaimana saya boleh mentakrifkan persatuan dalam Sequelize?
Sequelize memudahkan untuk menerangkan hubungan antara jadual. Anda boleh menetapkan hubungan satu-ke-satu, satu-ke-banyak, atau banyak-ke-banyak menggunakan kaedah mudah seperti hasOne, hasMany, dan belongsToMany. Sebagai contoh:
// 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' });Setelah ditetapkan, anda boleh menggunakan include dalam pertanyaan anda untuk secara automatik mengambil data yang berkaitan.
7. Bagaimana saya mengurus migrasi dan perubahan skema?
Dalam pembangunan, anda boleh menggunakan sequelize.sync() untuk membuat jadual dengan cepat. Tetapi dalam pengeluaran, anda harus sentiasa menggunakan migrasi. Migrasi ialah fail versi yang menerangkan bagaimana skema pangkalan data anda berubah dari masa ke masa, serupa dengan bagaimana komit Git menjejak perubahan kod.
Anda boleh membuat migrasi dengan CLI Sequelize:
npx sequelize-cli migration:generate --name add-users-tableSetiap migrasi mempunyai kaedah up dan down, satu untuk menerapkan perubahan dan satu untuk membatalkannya. Jalankan migrasi anda dengan:
npx sequelize-cli db:migrateDengan cara ini, setiap orang dalam pasukan anda (dan setiap penempatan) mengekalkan struktur pangkalan data yang sama.
Gunakan sequelize.sync() untuk eksperimen cepat, tetapi gunakan migrasi apabila aplikasi anda sudah hidup kerana ia lebih selamat, boleh diterbalikkan, dan lebih mudah untuk dijejak.
Kesimpulan
Dalam tutorial ini, anda menyediakan Sequelize dengan Node.js dan MySQL untuk mengurus data melalui model, hubungan, dan migrasi. Anda juga memastikan keselamatan kelayakan pangkalan data anda dengan menggunakan pembolehubah persekitaran dan meneroka amalan terbaik untuk menyelesaikan masalah serta menala prestasi.
Dengan langkah-langkah ini, anda kini mempunyai asas yang kukuh untuk membina dan menyelenggara aplikasi Node.js yang selamat dan cekap yang menggunakan Sequelize dan MySQL untuk pengurusan data.
Untuk mengetahui lebih lanjut tentang Sequelize, lihat dokumentasi produk. Untuk lebih banyak tutorial Node.js seperti ini, lihat artikel berikut:
- Cara Menyediakan Pelayan GraphQL dalam Node.js dengan Apollo Server dan Sequelize
- Cara Melaksanakan Caching dalam Node.js Menggunakan Redis
- Cara Membuat Pelayan Web dalam Node.js dengan Modul HTTP
Terima kasih kerana belajar bersama Komuniti Linux-Console.net.
