Jak používat Sequelize s Node.js a MySQL
Autor vybral Fond pro otevřený internet/volný projev, aby obdržel dar v rámci programu Psaní pro dary.
Úvod
Sequelize je objektově-relační mapper založený na Node.js, který usnadňuje práci s databázemi MySQL, MariaDB, SQLite, PostgreSQL a dalšími. Objektově-relační mapper provádí funkce jako práce s databázovými záznamy tím, že data reprezentuje jako objekty. Sequelize má výkonný migrační mechanismus, který dokáže převést existující schémata databáze na nové verze. Celkově Sequelize poskytuje vynikající podporu pro synchronizaci databází, eager loading, asociace, transakce a databázové migrace, přičemž zkracuje dobu vývoje a zabraňuje SQL injekcím.
V tomto tutoriálu si nainstalujete a nakonfigurujete Sequelize s MySQL ve vašem lokálním vývojovém prostředí. Dále použijete Sequelize k vytváření databází a modelů, stejně jako k provádění operací insert, select a delete. Poté vytvoříte Sequelize asociace pro vztahy one-to-one, one-to-many a many-to-many. Nakonec vytvoříte Sequelize raw dotazy pro nahrazování polí a objektů. Kromě těchto základů tutoriál také pokrývá bezpečnou konfiguraci databáze pomocí proměnných prostředí, bezpečné řízení změn schématu prostřednictvím migrací a nejlepší postupy pro řešení problémů a optimalizaci výkonu.
Nasazujte své frontendové aplikace z GitHubu pomocí platformy Linux-Console.net App. Nechte Linux-Console.net, aby se postaral o škálování vaší aplikace.
Hlavní závěry:
- Sequelize poskytuje snadný způsob, jak pracovat s MySQL pomocí modelů místo čistého SQL, což usnadňuje a zpřehledňuje operace s databází.
- Ukládání údajů pro přístup do databáze do proměnných prostředí udržuje citlivé informace v bezpečí a mimo verzovací systém.
- Používání migrací pro aktualizace schématu je bezpečnější než spoléhat se na
sequelize.sync(), zejména v produkčních prostředích. - Sequelize usnadňuje definování jedinečných, jeden-ku-mnohým a mnoho-ku-mnohým vztahů mezi modely.
- Surové SQL dotazy lze stále používat, když potřebujete větší kontrolu nebo lepší výkon pro složité databázové operace.
- Nejběžnější problémy se Sequelize, jako jsou selhání připojení nebo chyby migrace, lze vyřešit kontrolou proměnných prostředí, prohlížením záznamů a použitím nástrojů MySQL, jako jsou
EXPLAINaSHOW PROCESSLIST. - Výkon lze zlepšit optimalizací dotazů, přidáním správných indexů, laděním připojovacích poolů a ukládáním často přistupovaných dat do cache.
- Testování migrací, přidávání zpracování chyb a sledování výkonu databáze pomáhá udržovat aplikace Sequelize spolehlivé a připravené k provozu.
Předpoklady
K dokončení tohoto tutoriálu budete potřebovat:
- Vývojové prostředí běžící na Node.js. Chcete-li toto nastavit, postupujte podle návodu Jak nainstalovat Node.js a vytvořit místní vývojové prostředí pro váš operační systém.
- MySQL nainstalovaný ve vašem pracovním prostředí. Postupujte podle návodu Jak nainstalovat MySQL pro vaše prostředí, včetně kroků pro vytvoření uživatele.
- Znalost JavaScriptu a MySQL dotazů, kterou můžete rozvíjet pomocí série Jak kódovat v JavaScriptu a tutoriálu Úvod do dotazů v MySQL.
- Základní porozumění konceptům relačních databází, které najdete v tutoriálu Porozumění relačním databázím.
Tento tutoriál byl testován na verzi Node.js v24.11.1 a verzi npm 11.6.2.
Instalace a konfigurace Sequelize
V tomto kroku nainstalujete Sequelize a vytvoříte připojení k vaší MySQL databázi. Nejprve vytvoříte aplikaci Node.js. Poté nainstalujete Sequelize, nakonfigurujete MySQL databázi a vyvinete jednoduchou aplikaci.
Instalace Sequelize
Začněte vytvořením složky projektu. V tomto příkladu můžete použít hello-world. Jakmile je složka vytvořena, přejděte do ní pomocí terminálu:
mkdir hello-world
cd hello-worldPoté vytvořte ukázkovou aplikaci Node.js pomocí následujícího příkazu:
npm initDále budete vyzváni k odpovědi na několik úvodních otázek. Pro své nastavení použijte následující výstup. Stiskněte ENTER pro použití zobrazené výchozí hodnoty a nezapomeňte nastavit hlavní vstupní bod jako server.js. Tím se vytvoří struktura projektu, která je snadno udržovatelná.
Výstup bude vypadat následovně, což vyplní soubor 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"
}Dále vytvořte prázdný soubor server.js uvnitř složky projektu:
touch server.jsPo provedení předchozích kroků bude vaše konečná struktura složek vypadat takto:
hello-world/
├─ package.json
├─ server.js
Nyní můžete nainstalovat Sequelize pomocí následujícího příkazu:
npm i sequelizePo těchto aktualizacích soubor package.json nyní vypadá takto:
{
"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"
}
}V sekci dependencies nyní uvidíte závislost Sequelize.
Nastavili jste projekt a nainstalovali Sequelize. Dále vytvoříte ukázkovou databázi, ke které se připojíte.
Vytváření ukázkové databáze
V rámci předpokladů jste nainstalovali a nakonfigurovali MySQL, což zahrnovalo vytvoření uživatele. Nyní vytvoříte prázdnou databázi.
Chcete-li to provést, nejprve se musíte přihlásit ke své instanci MySQL. Pokud provozujete vzdálenou instanci, můžete použít svůj oblíbený nástroj. Pokud používáte lokálně běžící instanci MySQL, můžete použít následující příkaz, přičemž your_username nahraďte svým uživatelským jménem MySQL:
mysql -u your_username -p-u je uživatelské jméno a volba -p se zadává, pokud je účet chráněn heslem.
Server MySQL bude požadovat vaše databázové heslo. Zadejte své heslo a stiskněte ENTER.
Jakmile se přihlásíte, vytvořte databázi s názvem hello_world_db pomocí následujícího příkazu:
CREATE DATABASE hello_world_db;Chcete-li ověřit, zda jste databázi úspěšně vytvořili, můžete použít tento příkaz:
SHOW DATABASES;
Váš výstup bude podobný tomuto:
+--------------------+
| Database |
+--------------------+
| hello_world_db |
| information_schema |
| mysql |
| performance_schema |
| sys |
+--------------------+Po vytvoření vzorové databáze se odpojte od serveru MySQL:
mysql> QUITNyní musíte nainstalovat ruční ovladač pro vámi zvolenou databázi. Jelikož Sequelize poskytuje pouze funkce ORM, nezahrnuje vestavěné databázové ovladače. Proto budete muset nainstalovat ovladače podle své preference. Chcete-li to provést, přejděte v terminálu do adresáře projektu a nainstalujte do projektu ovladač MySQL pomocí následujícího příkazu:
npm install --save mysql2V tomto případě používáte ovladač pro MySQL.
Poznámka: Protože tento tutoriál používá MySQL jako databázi, používáte ovladač pro ni. V závislosti na vaší databázi můžete ovladač nainstalovat ručně takto:
npm install --save pg pg-hstore # Postgresnpm install --save mysql2npm install --save mariadbnpm install --save sqlite3npm install --save tedious # Microsoft SQL Server
Teď, když máte ukázkovou databázi, můžete vytvořit svou první aplikaci Sequelize s možností připojení k databázi.
Připojování k databázi MySQL
V této části připojíte aplikaci Node.js k databázi MySQL pomocí Sequelize.
Pro připojení k databázi otevřete soubor server.js k úpravám pomocí nano nebo vašeho oblíbeného editoru kódu:
nano server.jsZde vytvoříte připojení k databázi ve vaší aplikaci pomocí instance Sequelize. V metodě new Sequelize() předáte parametry serveru MySQL a přihlašovací údaje k databázi následujícím způsobem, přičemž DATABASE_USERNAME a DATABASE_PASSWORD nahraďte přihlašovacími údaji vašeho MySQL uživatele:
const Sequelize = require("sequelize");
const sequelize = new Sequelize(
'hello_world_db',
'DATABASE_USERNAME',
'DATABASE_PASSWORD',
{
host: 'DATABASE_HOST',
dialect: 'mysql'
}
);host je místo, kde je hostován server MySQL, takže budete muset zadat URL serveru nebo IP adresu. Pokud používáte lokálně nainstalovaný server MySQL, můžete nahradit DATABASE_HOST hodnotou localhost nebo 127.0.0.1.
Stejně tak, pokud používáte vzdálený server, ujistěte se, že nahradíte hodnoty připojení k databázi odpovídajícími údaji vzdáleného serveru.
Poznámka: Pokud používáte jakýkoli jiný databázový server, můžete parametr dialektu podle toho upravit.
Dále zavolejte metodu authenticate() založenou na slibu, abyste vytvořili připojení k databázi pro aplikaci. Chcete-li to provést, přidejte následující blok kódu do souboru server.js:
...
sequelize.authenticate().then(() => {
console.log('Connection has been established successfully.');
}).catch((error) => {
console.error('Unable to connect to the database: ', error);
});Metoda authenticate() se používá k připojení k databázi a testuje, zda jsou zadané přihlašovací údaje správné. Zde je připojení k databázi ve výchozím nastavení otevřené a stejné připojení lze použít pro všechny dotazy. Kdykoli potřebujete připojení zavřít, zavolejte metodu sequelize.close() po tomto volání authenticate(). Pro více informací o Sequelize, prosím, podívejte se na jejich průvodce začátky.
Většina metod poskytovaných Sequelize je asynchronní. To znamená, že můžete spouštět procesy ve své aplikaci, zatímco asynchronní blok kódu probíhá. Také po úspěšném provedení asynchronního bloku kódu vrací promise, což je hodnota vrácená na konci procesu. Proto můžete v asynchronních blocích kódu používat then(), catch() a finally() k vrácení zpracovaných dat.
V této fázi bude soubor server.js vypadat následovně:
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);
});Uložte soubor a zavřete ho.
V adresáři projektu spusťte aplikaci server.js pomocí následujícího příkazu:
node server.jsVáš výstup bude vypadat takto:
Connection has been established successfully!Databázové připojení bylo úspěšně vytvořeno.
V tomto kroku jste nainstalovali Sequelize, vytvořili ukázkovou databázi a použili Sequelize k připojení k databázi. Dále budete pracovat s modely v Sequelize.
Vytvoření databázové tabulky pomocí Sequelize
Nyní, když jste vytvořili ukázkovou databázi MySQL, můžete použít Sequelize k vytvoření tabulky a jejímu naplnění daty. V Sequelize se databázové tabulky označují jako modely. Model je abstrakce, která reprezentuje tabulku v databázi. Modely definují několik věcí pro Sequelize, například název tabulky, podrobnosti sloupců a datové typy. V tomto kroku vytvoříte model Sequelize pro data o knihách.
Nejprve vytvořte v adresáři projektu nový soubor s názvem book.model.js:
nano book.model.jsPodobně jako v předchozím kroku přidejte kód Sequelize pro inicializaci databáze s novým importem DataTypes na začátku souboru:
const { Sequelize, DataTypes } = require("sequelize");Sequelize obsahuje mnoho vestavěných datových typů. Chcete-li k nim přistupovat, přidáte import pro DataTypes. Tento tutoriál se odkazuje na některé často používané datové typy, jako jsou STRING, INTEGER a DATEONLY. Chcete-li se dozvědět více o dalších podporovaných datových typech, můžete se odkázat na oficiální dokumentaci Sequelize.
Poté zahrňte řádky, které jste dříve použili k vytvoření připojení k vaší databázi MySQL, a podle toho aktualizujte své přihlašovací údaje 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);
});Dále vytvoříte model nazvaný books, který bude obsahovat title, author, release_date a ID subject. K tomu použijte metodu sequelize.define() takto:
...
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,
}
});Metoda sequelize.define() definuje nový model, který představuje tabulku v databázi. Tento blok kódu vytvoří tabulku nazvanou books a ukládá záznamy o knihách podle title, author, release_date a subject.
V tomto kódu allowNull ukazuje, že hodnota sloupce modelu nemůže být null. Stejně tak, pokud potřebujete nastavit takovou hodnotu, můžete použít defaultValue: "value".
Dále přidáte model book do své databáze. K tomu použijete metodu sync() následujícím způsobem:
...
sequelize.sync().then(() => {
console.log('Book table created successfully!');
}).catch((error) => {
console.error('Unable to create table : ', error);
});V metodě sync() žádáte Sequelize, aby provedl několik úkonů s databází. Pomocí tohoto volání Sequelize automaticky provede SQL dotaz do databáze a vytvoří tabulku a zobrazí zprávu Tabulka knih úspěšně vytvořena!.
Jak bylo zmíněno, metoda sync() je metoda založená na promise, což znamená, že může také provádět zpracování chyb. V tomto bloku kódu zkontrolujete, zda byla tabulka úspěšně vytvořena. Pokud ne, vrátí chybu prostřednictvím metody catch a vypíše ji na výstup.
Poznámka: Synchronizaci modelu můžete spravovat předáním parametrů force, které vynutí vytvoření nové tabulky, pokud neexistuje, nebo naopak použijí tu stávající. Zde je několik příkladů, které vám mohou být užitečné při práci se Sequelize:
model.sync(): Tímto se vytvoří tabulka, pokud ještě neexistuje.model.sync({ force: true }): Tímto se vytvoří tabulka, přičemž se nejprve smaže, pokud již existuje stejná tabulka.
Konečný kód bude vypadat takto:
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);
});Uložte soubor a zavřete ho.
Spusťte svou aplikaci pomocí následujícího příkazu:
node book.model.jsNa příkazovém řádku dostanete následující výstup:
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!Ve výstupu uvidíte, že návratový protokol obsahuje zprávu Tabulka knihy byla úspěšně vytvořena!. Můžete to ověřit kontrolou vaší databáze, kde by měla být nová tabulka books vytvořena v databázi hello_world_db.
Chcete-li ověřit vytvoření nové tabulky, přihlaste se do své instance MySQL:
mysql -u YOUR_USERNAME -pPo zadání hesla přepněte do ukázkové databáze:
USE hello_world_db;A pak spusťte příkaz pro zobrazení tabulek:
SHOW TABLES;Váš výstup bude podobný tomuto:
+---------------------------+
| Tables_in_hello_world_db |
+---------------------------+
| books |
+---------------------------+
1 row in set (0.00 sec)Nakonec se odpojte od serveru MySQL:
mysql> QUITPotvrdili jste, že vytvoření modelu book bylo úspěšné. Pomocí tohoto postupu můžete vytvořit libovolný počet modelů následováním stejného postupu.
V tomto kroku jste vytvořili model v databázi a zahájili práci s modelem pomocí vestavěných metod. Také jste použili typy dat podporované Sequelize k definování svého modelu. Dále budete pracovat se základními dotazy na model.
Používání Sequelize pro dotazy do databáze
V tomto kroku budete používat vestavěné dotazy Sequelize pro vkládání, výběr, výběr s podmíněnými klauzulemi a mazání.
Vkládání nového záznamu
V předchozím kroku jste vytvořili model book v databázi. V této části do tohoto modelu vložíte data.
Chcete-li začít, zkopírujte obsah souboru book.model.js z předchozího kroku. Vytvořte nový soubor s názvem book.controller.js, který bude zajišťovat logiku dotazů. Přidejte kód ze souboru book.model.js do book.controller.js.
V souboru book.controller.js najděte metodu sync(). Do metody sync() přidejte následující zvýrazněné řádky:
...
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);
});Zde vložíte nový záznam o knize do modelu books, který jste již vytvořili, pomocí metody sync(), která podporuje přidávání nových záznamů do již vytvořených modelů. Jakmile se metoda sync() úspěšně provede, spustí se metoda then(). Uvnitř metody then() voláte metodu create(), aby se nové záznamy vložily do modelu.
Metodu create() používáte k předání dat, která chcete přidat do databáze, jako objekt. Zvýrazněná část kódu vloží nový záznam do vaší existující tabulky books. V tomto příkladu přidáváte Clean Code od Roberta Cecila Martina, který je zařazen do kategorie s ID 3. Stejný kód můžete použít, aktualizovaný o informace pro jiné knihy, k přidání nových záznamů do databáze.
Uložte soubor a zavřete ho.
Spusťte aplikaci pomocí následujícího příkazu:
node book.controller.jsVáš výstup bude vypadat podobně jako následující:
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,
...
}Do modelu, který jste vytvořili v databázi, jste vložili nový záznam. Můžete pokračovat v přidávání více záznamů stejným způsobem.
Výběr všech záznamů
V této části vyberete a získáte všechny záznamy knih z databáze pomocí metody findAll(). Nejprve otevřete book.controller.js a odstraňte předchozí metodu Book.create(). V metodě sync() přidejte metodu Book.findAll() takto:
...
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);
});
...Uložte soubor a zavřete ho.
Poté spusťte aplikaci znovu pomocí následujícího příkazu:
node book.controller.jsVáš výstup bude vypadat podobně jako následující:
[
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
},
...
]Výstup obsahuje všechna data o knihách jako pole objektů. Úspěšně jste použili metodu Sequelize findAll(), aby se vrátila všechna data o knihách z databáze.
Výběr pomocí klauzule where
V této části vyberete hodnoty s podmínkami pomocí klauzule where. Klauzule where se používá k určení podmínky při načítání dat. V tomto tutoriálu získáte knihu podle konkrétního ID záznamu z databáze pomocí metody findOne().
Chcete-li to provést, otevřete book.controller.js k úpravám, odstraňte metodu findAll() a přidejte následující řádky:
...
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);
});Zde vyberete konkrétní záznam knihy z databáze pomocí metody findOne() s možností where. V tomto příkladu získáváte údaje o knize, jejíž id je rovno 1.
Uložit a zavřít soubor.
Dále spusťte aplikaci:
node book.controller.jsVáš výstup bude vypadat podobně jako následující:
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
},
...
}Úspěšně jste použili klauzule where pro získávání dat z modelů Sequelize. Klauzuli where můžete v databázové aplikaci použít k zachycení podmíněných dat.
Mazání záznamu
Chcete-li smazat konkrétní záznam z databázového modelu, použijte metodu destroy() s volbou where. K tomu otevřete soubor book.controller.js, odstraňte metodu findOne() a přidejte následující zvýrazněné řádky:
...
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);
});Zde odstraníte záznam knihy z databáze pomocí metody destroy() s volbou where a předáním id knihy, kterou chcete odstranit. Budete odstraňovat záznam knihy, jejíž id se rovná 2.
Uložit a zavřít soubor.
Dále spusťte aplikaci:
node book.controller.jsVáš výstup bude vypadat takto:
Successfully deleted record.Záznam byl smazán.
V tomto kroku jste experimentovali se svým databázovým modelem a dotazováním modelu. Inicializovali jste databázi, vytvořili modely, vložili záznamy, načetli záznamy, načetli záznamy s podmínkami pomocí klauzule where a odstranili vybrané záznamy. S těmito znalostmi Sequelize nyní vytvoříte asociace v Sequelize. Poté budete schopni definovat a pracovat s různými vztahy pomocí modelů Sequelize.
Vytváření asociací pomocí Sequelize
V tomto kroku budete používat standardní typy asociací, které Sequelize podporuje: jeden k jednomu, jeden k mnoha a mnoho k mnoha. Budete používat ukázková data o studentech, kurzech a úrovních známek.
Sequelize používá typy asociací založené na následujících databázových vztazích:
one-to-one vztah: Vztah one-to-one znamená, že záznam v jedné tabulce je spojen přesně s jedním záznamem v jiné tabulce. Z pohledu Sequelize můžete použít asociace
belongsTo()ahasOne()k vytvoření tohoto typu vztahu.vztah jeden k mnoha: Vztah jeden k mnoha znamená, že jeden záznam v jedné tabulce je spojen s několika záznamy v jiné tabulce. Se Sequelize můžete použít metody asociací
hasMany()k vytvoření tohoto typu vztahu.vztah mnoho k mnoha: Vztah mnoho k mnoha znamená, že více záznamů v jedné tabulce je spojeno s více záznamy v jiné tabulce. Se Sequelize můžete použít asociace
belongsToMany()k vytvoření tohoto typu vztahu.
Před vytvořením těchto asociací nejprve vytvoříte novou databázi s názvem student_db a přidáte nové modely a některá ukázková data pro studenty, kurzy a úroveň hodnocení.
Chcete-li vytvořit databázi, postupujte stejným způsobem jako při instalaci a konfiguraci Sequelize pro přihlášení do MySQL a vytvoření databáze s názvem student_db. Jakmile bude nová databáze vytvořena, odhlaste se z MySQL. Poté začnete vytvářet asociace databáze.
Vytvoření jednoznačného vztahu pomocí belongsTo()
V této části vytvoříte vztah jeden k jednomu pomocí modelů Sequelize. Představte si, že chcete získat podrobnosti o jednom studentovi spolu s jeho úrovní ročníku. Protože jeden student může mít pouze jednu úroveň ročníku, tento typ propojení je vztah jeden k jednomu a můžete použít metodu belongsTo().
Poznámka: Existuje rozdíl mezi belongsTo() a hasOne(). belongsTo() přidá foreignKey do zdrojové tabulky, zatímco hasOne() jej přidá do cílové tabulky. V každém případě, pokud jsou oba vztahy použity současně, bude to fungovat jako obousměrné vztahy jeden-na-jeden v Sequelize.
Metoda belongsTo() vám umožňuje vytvořit vztah jeden k jednomu mezi dvěma modely Sequelize. V tomto příkladu používáte modely Student a Grade.
Vytvořte nový soubor s názvem one_to_one.js. Stejně jako jste to udělali v předchozí části, Připojení k databázi MySQL, zahrňte do horní části souboru řádky pro vytvoření připojení k databázi a ověření vašeho uživatele MySQL. Nezapomeňte podle potřeby aktualizovat přihlašovací údaje 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);
});V této části vytvoříte tři modely v nové databázi student_db: Student, Grade a Course. Začnete vytvořením modelů Student a Grade. Později v tomto kroku vytvoříte model Course.
Pro model Student přidejte následující blok kódu do souboru 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
}
});Tento studentský model obsahuje dva sloupce: student_id a name.
Dále přidejte blok kódu pro model Grade:
...
const Grade = sequelize.define("grades", {
grade: {
type: DataTypes.INTEGER,
allowNull: false
}
});Model Grade obsahuje sloupec grade.
Aby bylo možné předvést asociace, budete muset do databáze přidat ukázková data. K tomu použijete metodu bulk(). Místo vkládání dat do řádků jednotlivě vám metoda bulkCreate() umožní vložit více řádků do vašich databázových modelů najednou.
Tak nyní naimportujte data Grade a Student do jejich příslušných modelů v databázi, jak je ukázáno:
...
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);
});Zde poskytnete ukázková data a vložíte je do modelů Student a Grade. S vaší databází, modely a ukázkovými daty připravenými, jste připraveni vytvořit asociace.
V souboru one-to-one.js přidejte následující řádek pod blok student_data:
...
Student.belongsTo(Grade);Dále budete muset zkontrolovat, zda asociace funguje správně. K tomu můžete získat data všech studentů spolu s přiřazenými stupni tím, že předáte parametr include uvnitř metody findAll().
Protože potřebujete získat úroveň studenta, předáte Grade jako model. V metodě sequelize.sync() přidejte zvýrazněné řádky, jak je uvedeno:
...
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);
});Kompletní kód vypadá následovně:
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);
});Uložte soubor a zavřete ho.
Spusťte soubor pomocí následujícího příkazu:
node one_to_one.jsVýstup bude dlouhý a uvidíte data všech studentů s jejich stupni. Zde je ukázka výstupu zobrazujícího údaje o studentech:
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:
...V závislosti na používaných nástrojích příkazového řádku se výstup může zobrazit jako rozšířený pohled nebo ne. Pokud se jedná o rozšířený pohled, vypíše se rozšířený objekt grade jako výstup.
V této části jste vytvořili jedinečné propojení pomocí volání metody Student.belongsTo(Grade); a získali podrobnosti podle vytvořeného spojení.
Vytvoření vztahu jeden-k-mnohým pomocí hasMany()
V této části vytvoříte vztah jeden k mnoha pomocí modelů Sequelize. Představte si, že chcete získat všechny studenty spojené s vybranou úrovní třídy. Protože jedna konkrétní úroveň třídy může mít více studentů, jedná se o vztah jeden k mnoha.
Chcete-li začít, zkopírujte obsah souboru one_to_one.js do nového souboru nazvaného one_to_many.js. Ve souboru one_to_many.js odstraňte řádky po bloku student_data. Váš soubor one_to_many.js bude vypadat takto:
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}
]Po bloku student_data použijte metodu hasMany() k vytvoření nového vztahu:
...
Grade.hasMany(Student)Metoda hasMany() vám umožňuje vytvořit vztah typu jeden-k-mnoha mezi dvěma modely Sequelize. Zde používáte modely Grade a Student.
Dále přidejte metodu sequelize.sync() spolu s metodou findAll() pod řádek 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);
});Zde se pokoušíte získat přístup ke všem studentům na určité úrovni třídy – v tomto případě ke všem studentům 9. třídy. Také jste do možnosti include přidali model Student.
Zde je kompletní kód:
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);
});Uložte soubor a zavřete ho.
Spusťte soubor následujícím příkazem:
node one_to_many.jsVýstup bude vypadat podobně jako následující. Bude poměrně dlouhý, ale všichni studenti v ročníku 9 budou vráceni takto:
[ 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 },
...V této části jste vytvořili vztah jeden k mnoha pomocí volání metody Grade.hasMany(Student);. Ve výstupu jste načetli podrobnosti podle asociace, kterou jste vytvořili.
Vytváření vztahů mnoho k mnoha pomocí belongsToMany()
V této části vytvoříte vztahy mnoho k mnoha pomocí modelů Sequelize. Jako příklad si představte situaci, kdy jsou studenti zapsáni do kurzů. Jeden student se může zapsat do mnoha kurzů a jeden kurz může mít mnoho studentů. To je vztah mnoho k mnoha. Pro implementaci tohoto vztahu pomocí Sequelize použijete modely Student, Course a StudentCourse s metodou belongsToMany().
Chcete-li začít, vytvořte soubor s názvem many_to_many.js a přidejte bloky kódu pro inicializaci a autentizaci databáze následovně. (Bloky kódu můžete znovu použít z předchozího příkladu one_to_many.js.) Ujistěte se, že podle potřeby aktualizujete zvýrazněné hodnoty připojení k databázi.
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);
});Dále vytvoříte databázové modely pro vztahy mnoho-k-mnoha: Student a Course. Poté přidáte do těchto modelů několik ukázkových dat.
...
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},
]Zde vytvoříte modely Student a Course a poskytnete některá ukázková data. Také nastavíte courseID, které použijete k získání studentů podle tohoto typu vztahu.
Nakonec jste definoval nový model nazvaný StudentCourse, který spravuje vztahová data mezi Student a Course. V tomto příkladu je studentId 1 zapsán do courseId 1 a courseId 2.
Dokončili jste inicializaci databáze a přidali ukázková data do databáze. Dále vytvořte vztahy mnoho k mnoha pomocí metody belongsToMany(), jak je ukázáno:
...
Course.belongsToMany(Student, { through: 'StudentCourse'})
Student.belongsToMany(Course, { through: 'StudentCourse'})V metodě belongsToMany() předáte konfiguraci through s názvem modelu jako konfigurační možnost. V tomto případě je to StudentCourse. Toto je tabulka, která spravuje vztahy mnoho k mnoha.
Nakonec můžete zkontrolovat, zda asociace funguje správně, tím, že načtete všechna data kurzů spolu s přiřazenými studenty. Uděláte to tak, že předáte parametr include uvnitř metody findAll(). Přidejte následující řádky do souboru 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);
});Kompletní kód vypadá následovně:
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);
});Uložte soubor a zavřete ho.
Spusťte soubor pomocí následujícího příkazu:
node many_to_many.jsVýstup bude dlouhý, ale bude vypadat zhruba následovně:
[ 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:
...Jak můžete vidět v tomto výstupu, byly načteny kurzy s přiřazenými studenty. V bloku courses uvidíte samostatné hodnoty id, které označují každý kurz. Například id: 1 je spojeno s course_name: Science pro kurz Science, zatímco id: 2 je kurz Maths, a tak dále.
V databázi můžete vidět tři vygenerované tabulky s ukázkovými daty, která jste vložili.
V tomto kroku jste použili Sequelize k vytvoření vazeb jeden na jednoho, jeden na mnoho a mnoho na mnoho. Dále budete pracovat s prostými dotazy.
Práce s neformátovanými dotazy
V tomto kroku budete pracovat s raw dotazy v Sequelize. V předchozích krocích jste používali vestavěné metody Sequelize, jako jsou insert() a findAll(), k vkládání dat a jejich výběru z databáze. Možná jste si všimli, že tyto metody mají specifický vzor pro psaní dotazu. Nicméně při použití raw dotazů se nemusíte starat o vestavěné metody a vzory Sequelize. Díky znalostem SQL dotazů můžete provádět v Sequelize různé dotazy od jednoduchých po složitější.
Zde je příklad surových dotazů, které provádějí akci výběru všech hodnot z určité tabulky, mazání vybraných hodnot podle podmínky a aktualizace tabulky s danými hodnotami.
SELECT * FROM table_name;
DELETE FROM table_name WHERE condition;
UPDATE table_name SET y = 42 WHERE x = 12;V Sequelize lze používat tzv. raw dotazy primárně dvěma metodami: nahrazením polem a nahrazením objektem. Když předáváte hodnoty do SQL dotazu, můžete k této náhradě použít buď pole, nebo objekt.
Než začnete psát surový dotaz, budete nejprve muset zadat údaje o studentech do ukázkové databáze. Po předchozí části, Vytváření ukázkové databáze, se přihlaste do MySQL, vytvořte databázi s názvem sample_student_db a odhlaste se z MySQL.
Dále přidáte nějaká surová data, abyste mohli začít pracovat se surovými dotazy. Vytvořte nový soubor s názvem add_student_records.js a přidejte následující bloky kódu, které obsahují dříve diskutované metody Sequelize authenticate(), sync() a 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);
});Zde zahájíte připojení k databázi, vytvoříte model a vložíte několik záznamů studentů do nové databáze.
Uložte soubor a zavřete ho.
Dále spusťte tento skript pomocí následujícího příkazu:
node add_student_records.jsVýstup bude něčím podobný následujícímu. Bude poměrně dlouhý, ale všechny záznamy studentů, které jste vložili, budou vráceny následovně. Všimněte si, že protože student_id je automaticky generovaná hodnota UUID (Universally Unique Identifiers), bude se lišit v závislosti na uživateli.
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
},
…V další části budete aplikovat surové dotazy pomocí jednoho z výstupů student_id ve výše uvedeném bloku kódu. Zkopírujte si ho, abyste ho měli pro následující části, kde budete používat metodu query() pro nahrazování polí a objektů.
Nahrazení pole
V této části budete používat metodu query() pro nahrazení pole. Pomocí této metody může Sequelize provádět surové SQL dotazy nebo již připravené SQL dotazy.
Chcete-li začít, zkopírujte obsah souboru server.js z Kroku 1, protože ten obsahuje metodu Sequelize() pro inicializaci a spuštění databáze. Vložte obsah do nového souboru s názvem array_raw_query.js. Aktualizujte název databáze na 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);
});Na konci souboru přidejte následující blok kódu pro nahrazení pole, přičemž se ujistěte, že REPLACE_STUDENT_ID nahradíte hodnotou student_id, kterou jste zkopírovali v předchozí části.
...
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);
});Pro nahrazení pole předáte metodě query() SQL dotaz a konfigurační objekt. Ten obsahuje hodnotu a typ replacements. Pro nahrazení předáte data jako pole a tyto hodnoty zachytíte pomocí otazníku (?) symbolu.
Dále, protože potřebujete získat data o konkrétním studentovi, student_id je předáno jako druhý parametr. Poté předáte dvojici klíč-hodnota type: sequelize.QueryTypes.SELECT, kterou můžete použít k výběru dat z databáze.
Existují také jiné typy, jako například QueryTypes.UPDATE a QueryTypes.DELETE. V závislosti na požadavku si můžete vybrat typ, který vyhovuje vašemu účelu.
Následuje celý blok kódu. Zde se připojíte k databázi a získáte vybraná data studenta pomocí surového dotazu.
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);
});Uložte soubor a zavřete ho.
Dále můžete tento skript spustit pomocí následujícího příkazu:
node array_raw_query.jsUvidíte výstup podobný následujícímu:
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 } ]Kvůli vybranému student_id se mohou vaše výstupní hodnoty lišit.
Nahrazení objektu
Na povrchu je nahrazování objektů podobné nahrazování polí, ale způsob předávání dat do surového dotazu se liší. V možnosti nahrazení předáváte data jako objekt, a v možností dotazu používáte hodnoty jako :key.
Chcete-li začít, vytvořte nový soubor s názvem object_raw_query.js a vložte celé bloky kódu ze souboru server.js, přičemž aktualizujte databázi na 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);
});Poté přidejte následující blok kódu na konec nového souboru 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);
});Zde získáte vybraná data studenta pomocí metody nahrazování objektu. Vytvoříte objekt replacement a nastavíte id jako informace o studentovi, které chcete získat: { id: '<mark>>REPLACE_STUDENT_ID</mark>' }.
V query() uvádíte: 'SELECT * FROM students WHERE student_id=:id'. Pomocí metody query() předáváte hodnotu náhrady jako objekt, a proto je tato metoda známá jako náhrada objektem.
Zde je kompletní kód:
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);
});Uložte soubor a zavřete ho.
Dále spusťte tento skript pomocí následujícího příkazu:
node object_raw_query.jsVýstup bude vypadat podobně jako následující:
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 } ]Kvůli vybranému student_id se mohou vaše výstupní hodnoty lišit.
V tomto kroku jste pracovali s raw dotazy Sequelize pomocí dvou různých metodologií: nahrazování polí a nahrazování objektů.
Konfigurace proměnných prostředí pro zabezpečená připojení k databázi
Do tohoto bodu jste uchovávali přihlašovací údaje k databázi přímo ve svém kódu. I když tento přístup funguje pro lokální experimentování, není bezpečný. Pevně zadané přihlašovací údaje odhalují citlivé informace, jako jsou hesla k databázi a názvy hostitelů, a zvyšují riziko narušení bezpečnosti při sdílení nebo nasazení kódu. V této části se naučíte, jak tyto přihlašovací údaje bezpečně uchovávat pomocí proměnných prostředí.
Proč používat proměnné prostředí?
Proměnné prostředí fungují jako externí konfigurační parametry, které může vaše aplikace číst při běhu. Místo toho, abyste přímo do kódu vkládali přihlašovací údaje, jsou uloženy ve vašem systému nebo v samostatném konfiguračním souboru, který se nikdy nezavádí do verzovacího systému. Tento přístup přináší několik výhod:
- Bezpečnost: Vaše přihlašovací údaje zůstávají skryté před veřejnými úložišti a systémy správy verzí.
- Flexibilita: Každé prostředí (vývojové, testovací, produkční) může používat jinou konfiguraci databáze, aniž by se měnil zdrojový kód.
- Udržovatelnost: Centralizovaná konfigurace umožňuje snadné aktualizace; pokud se změní heslo k databázi, musíte upravit pouze jeden soubor nebo proměnnou.
- Shoda: Tato praxe je v souladu s metodikou Twelve-Factor App, která podporuje správu konfigurace specifickou pro jednotlivá prostředí pro škálovatelné aplikace.
Nastavení proměnných prostředí
Budete používat balíček dotenv k spravování svých environmentálních proměnných v Node.js. Tato knihovna načítá proměnné ze souboru .env a vkládá je do objektu process.env v Node.js, díky čemuž jsou přístupné v celé vaší aplikaci.
Nainstalujte balíček dotenv spuštěním následujícího příkazu:
npm install dotenvPo instalaci vytvořte v kořenovém adresáři vašeho projektu nový soubor s názvem .env. Tento soubor bude obsahovat všechna citlivá data potřebná pro připojení k databázi.
Zde je příklad konfigurace souboru .env pro vaše nastavení Sequelize:
DB_NAME=hello_world_db
DB_USER=your_username
DB_PASSWORD=your_password
DB_HOST=localhost
DB_DIALECT=mysqlKaždá proměnná odpovídá konkrétnímu parametru, který Sequelize používá k navázání spojení.
Zajištění souboru .env
Je zásadní, aby váš soubor .env nikdy nebyl součástí verzovacího systému. Abyste tomu zabránili, přidejte ho do souboru .gitignore, aby jej Git při commitování změn přeskočil:
.envV produkčních prostředích jsou proměnné prostředí obvykle konfigurovány přímo v nastavení vaší hostingové platformy nebo v správci tajemství, spíše než v lokálním souboru .env.
Aktualizace vaší konfigurace Sequelize
Nyní, když jste definovali proměnné prostředí, aktualizujte svou inicializaci Sequelize tak, aby je používala. Začněte naimportováním a nakonfigurováním dotenv na začátku hlavního souboru serveru (např. 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);
});- Řádek
require('dotenv').config()načte všechny proměnné definované v souboru.envdoprocess.env. - Sequelize načítá proměnné prostředí při inicializaci nové instance.
- To zajišťuje, že žádné citlivé informace, jako uživatelská jména nebo hesla, se ve vašem kódu neobjeví.
Tento přístup zvyšuje bezpečnost a umožňuje různým prostředím používat jedinečné konfigurace jednoduše změnou hodnot proměnných prostředí.
Ověření konfigurace
Jakmile aktualizujete svou konfiguraci, můžete ověřit spojení spuštěním své aplikace Node.js:
node server.jsPokud je váš soubor .env správně nastaven a server MySQL běží, uvidíte následující výstup:
Connection has been established successfully.Pokud se objeví chyba, zkontrolujte, zda:
- Přihlašovací údaje ve vašem souboru
.envodpovídají těm ve vaší instanci MySQL. - Server MySQL běží a je přístupný z vašeho počítače.
- Soubor
.envse nachází v kořenovém adresáři vašeho projektu a je správně naformátován.
Nejlepší postupy pro bezpečnou konfiguraci
Používání proměnných prostředí je silným prvním krokem k bezpečné správě konfigurace. Pro zajištění trvalé bezpečnosti a spolehlivosti zvažte následující další osvědčené postupy:
- Používejte samostatné konfigurace pro každé prostředí: Udržujte různé soubory
.envprodevelopment,stagingaproduction. Můžete je pojmenovat.env.development,.env.staginga.env.production. - Využívejte správce tajemství: Pro produkční prostředí používejte správce tajemství místo ukládání tajemství do souborů.
- Ověření proměnných prostředí: Použijte konfigurační nástroj nebo spouštěcí skript, který zkontroluje, zda jsou požadované proměnné definovány před spuštěním aplikace. To pomáhá předejít chybám během běhu programu.
- Pravidelně měňte přihlašovací údaje: Pravidelně aktualizujte přihlašovací údaje k databázi, abyste snížili dopad případných úniků.
- Omezte přístup k databázi: Nakonfigurujte role uživatelů databáze tak, aby měly pouze nejmenší potřebná oprávnění pro aplikaci.
Použitím proměnných prostředí a dodržováním těchto postupů zajistíte, že vaše aplikace Sequelize si udrží jak flexibilitu, tak bezpečnost napříč vývojovým a produkčním prostředím.
Nejlepší postupy při migraci a synchronizaci
Při vývoji databázového schématu máte u Sequelize dva hlavní přístupy: psát a spouštět explicitní migrace, nebo používat sequelize.sync(), aby Sequelize automaticky generoval změny schématu. Oba přístupy jsou platné, ale slouží různým účelům a mají své nevýhody. Pojďme pochopit, kdy použít který, jak psát bezpečné migrace a jak je spolehlivě spouštět ve vývoji i v produkci.
Migrace vs sequelize.sync() — kdy použít kterou
Migrace (doporučeno pro produkci): Migrace jsou explicitní, verzované změny vašeho schématu. Jsou ukládány do verzovacího systému, podléhají revizi kódu a provádějí se jako součást vašeho nasazovacího procesu. Používejte migrace v produkci pro jakoukoli změnu schématu, která ovlivňuje integritu nebo dostupnost dat.
sequelize.sync()(používejte pouze pro vývoj a prototypy):sync()je vhodné pro lokální vývoj, testy a rychlé prototypy, protože může automaticky vytvářet nebo upravovat tabulky. Nepoužívejte všaksync({ force: true })nebosync({ alter: true })v produkci: tyto možnosti mohou odstranit data nebo provést nebezpečné změny bez možnosti řízeného vrácení zpět.
Nástroje: sequelize-cli a spouštěče migrací
Oficiální CLI, sequelize-cli, je nejjednodušší způsob, jak spravovat migrace se Sequelize. Pro týmy, které potřebují větší kontrolu nebo vlastní pracovní postupy, je umzug oblíbenou alternativou.
Chcete-li nainstalovat a inicializovat CLI ve svém projektu, spusťte:
npm install --save-dev sequelize-cli
npx sequelize-cli initTím se vytvoří následující složky:
config/ # Stores database configuration files
models/ # Stores your Sequelize model definitions
migrations/ # Stores migration files
seeders/ # Stores seeder files for inserting initial dataTyto složky byste měli přidat do verzovacího systému (kromě souborů obsahujících přihlašovací údaje). To zajistí, že každé prostředí bude konzistentně provádět stejné změny v databázi.
Vytváření a spouštění migrací
Chcete-li vytvořit nový migrační soubor, použijte následující příkaz:
npx sequelize-cli migration:generate --name add-isbn-to-booksTímto se vytvoří soubor s časovou značkou ve složce migrations/. Otevřete soubor a definujte, co by se mělo stát při použití migrace (up) a jak ji vrátit zpět (down):
module.exports = {
async up(queryInterface, Sequelize) {
await queryInterface.addColumn('books', 'isbn', {
type: Sequelize.STRING
});
},
async down(queryInterface) {
await queryInterface.removeColumn('books', 'isbn');
}
};- Funkce
upaplikuje migraci (přidá sloupec). - Funkce
downvrací změnu zpět (odstraní sloupec).
Spusťte migraci pomocí:
npx sequelize-cli db:migrateChcete‑li vrátit poslední migraci, použijte:
npx sequelize-cli db:migrate:undoMůžete také vrátit všechny migrace ve vývoji spuštěním:
npx sequelize-cli db:migrate:undo:allPsání bezpečných, idempotentních migrací
Při vytváření migrací dodržujte tato pravidla:
Zabalte operace do transakcí, pokud je to podporováno databází. To zajistí, že migrace buď úplně proběhne, nebo se v případě chyby kompletně vrátí zpět.
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 }); }); } };Udržujte migrace malé a zaměřené. Každá migrace by měla provést jedinou logickou změnu (přidání sloupce, vytvoření indexu, přejmenování sloupce). Menší migrace se snáze kontrolují, testují a vracejí zpět.
Buďte opatrní a nezpůsobujte opakované změny. Když je to vhodné, zkontrolujte existenci, abyste se vyhnuli chybám v prostředích s rozdíly. Použijte
queryInterface.describeTable()nebo surové dotazy k ochraně operací.Vyvarujte se destruktivních operací na jeden krok. Například, pokud chcete bezpečně odstranit sloupec, nejprve přidejte nový sloupec, naplňte ho daty, přesměrujte čtení na nový sloupec v aplikačním kódu a až poté odstraňte starý sloupec v pozdější migraci.
Dlouhotrvající migrace bez výpadků
Velké tabulky a operace s indexy mohou způsobovat zámky. Použijte tyto strategie ke snížení dopadu:
- Nejprve přidejte sloupce, které mohou obsahovat hodnotu NULL. Přidání sloupce, který může být NULL, je obvykle rychlé. Vyhněte se přidávání sloupců s nenulovými výchozími hodnotami, které způsobují přepsání celé tabulky.
- Doplňujte postupně v malých dávkách. Zavést úlohu na pozadí pro naplnění nových sloupců po částech, místo aby se spouštělo jedno obrovské
UPDATE. - Vytvářejte indexy bez exkluzivních zámků, pokud je to možné. Používejte databázově specifické funkce (například Postgres
CONCURRENTLYa novější MySQL online DDL) pomocí čistého SQL v migracích. - Postupné zavádění pomocí feature-flagů. Nasazujte kód aplikace, který čte nový sloupec za feature-flagem. Po dokončení doplňování dat a úspěšném průchodu testů přepněte flag a později odstraňte staré pole.
Vrácení zpět a nouzové opravy
- Poskytněte migraci
down. Každéupby mělo mít opačnédown, které dokumentuje, jak změnu vrátit. I kdyždownv produkci spouštíte jen zřídka, slouží jako jasný plán pro vrácení změn. - Plánujte nouzové návraty zpět. Pokud migrace způsobí problémy, buďte připraveni nejprve vrátit zpět kód aplikace a v případě potřeby obnovit databázi ze záloh. Pravidelně testujte postupy obnovy.
Zasévání dat a změny schématu
- Udržujte seedery na minimální a stabilní úrovni. Používejte seedery pro nezbytné řádky pro vyhledávání nebo konfiguraci. Vyhněte se zadávání velkého objemu obchodních dat prostřednictvím migrací.
- Oddělte semena od strukturálních migrací. Pokud musíte naplnit data, která závisí na změně schématu, upřednostněte následný seeder, aby zůstaly odpovědnosti jasné.
CI, kontrola kódu a automatizace nasazení
Nejprve spusťte migrace v CI a stagingu. Přidejte krok v CI, který spustí migrace na dočasné databázi, aby se chyby odhalily co nejdříve.
Chovej se k migracím stejně jako kódu. Kontrolujte a prověřujte soubory migrací v pull requestech. Kde je možné, zahrňte automatizované kontroly.
Automatizujte provádění migrací během nasazování. Ujistěte se, že migrace proběhnou předtím, než aplikační procesy začnou přijímat provoz. Příklad skriptů v
package.json:"scripts": { "migrate": "npx sequelize-cli db:migrate", "start": "node server.js", "deploy": "npm run migrate && npm run start" }
V konteinerových nasazeních spouštějte migrace jako init kontejner nebo v nasazovacím hooku, aby webové procesy začaly až po dokončení migrací.
Testování migrací
- Otestujte oba směry. Spusťte
db:migratea potédb:migrate:undo:alllokálně i v CI, abyste ověřili, žeupidownfungují. - Používejte jednorázové databáze pro testy. Upřednostňujte efemérní databáze nebo kontejnery pro deterministické běhy testů.
Dodržování těchto osvědčených postupů zajišťuje, že vaše Sequelize migrace zůstanou spolehlivé, sledovatelné a bezpečné pro dlouhodobé projekty.
Tipy pro odstraňování problémů a zlepšení výkonu
I přes solidní nastavení mohou aplikace používající Sequelize někdy narazit na nečekané problémy, jako jsou chyby připojení k databázi, selhání migrace, pomalu běžící dotazy, zablokování nebo konflikty souběžného přístupu. Tato sekce poskytuje postupný návod, jak tyto problémy identifikovat a opravit, spolu s doporučeními pro výkon, která vám pomohou udržet vaši aplikaci stabilní a efektivní.
Řešení běžných problémů
1. Chyby připojení
Problém: Sequelize se nemůže připojit k databázi MySQL a vrací chyby jako SequelizeConnectionError: connect ECONNREFUSED, Access denied for user nebo SequelizeHostNotFoundError.
Jak opravit:
Začněte tím, že potvrdíte, že jsou vaše přihlašovací údaje správné. Dvakrát zkontrolujte hodnoty ve vašem souboru .env, včetně názvu databáze, uživatelského jména, hesla, hostitele a portu. I malá chyba nebo mezera na konci může způsobit, že se Sequelize nepřipojí.
Dále se ujistěte, že váš server MySQL běží a naslouchá na výchozím portu (3306). Připojení můžete otestovat ručním přihlášením:
mysql -u your_username -p -h your_host -P 3306Pokud tento příkaz selže, problém pravděpodobně spočívá ve vaší službě MySQL nebo přihlašovacích údajích.
Pokud používáte balíček dotenv, ujistěte se, že require('dotenv').config() se objeví před inicializací Sequelize. Tento krok zajistí, že všechny proměnné prostředí budou dostupné během běhu programu.
Nakonec, u vzdálených připojení ověřte nastavení svého firewallu nebo pravidla bezpečnostních skupin. MySQL server musí přijímat příchozí připojení z hostitele vaší aplikace.
2. Selhání migrace
Problém: Spustíte npx sequelize-cli db:migrate nebo sequelize.sync() a narazíte na chyby, jako jsou chybějící tabulky, duplicitní sloupce nebo nesoulad schématu.
Jak opravit:
Problémy s migracemi obvykle nastávají, když jsou soubory spouštěny ve špatném pořadí nebo obsahují chyby v SQL operacích. Sequelize zpracovává migrace na základě časových značek v názvech souborů, proto se ujistěte, že jsou soubory správně pojmenované.
Pokud migrace selže, podrobně si prohlédněte chybovou zprávu. Poté bezpečně vraťte poslední migraci pomocí:
npx sequelize-cli db:migrate:undoPo opravě migračního souboru jej znovu spusťte.
Vždy zabalte svou migrační logiku do transakce, aby byla zajištěna atomickost: buď všechny změny proběhnou úspěšně, nebo žádná. Před spuštěním migrací na produkci je důkladně otestujte na stagingové nebo lokální databázi, aby byla potvrzena jejich správnost.
3. Problémy se synchronizací modelu
Problém: Vaše modely Sequelize a schéma databáze si neodpovídají, což vede k chybějícím sloupcům, nesprávným datovým typům nebo zastaralým tabulkám.
Jak opravit:
Vyvarujte se používání sequelize.sync({ force: true }) v produkci, protože to odstraní a znovu vytvoří tabulky, což může způsobit nevratnou ztrátu dat. Podobně používejte sequelize.sync({ alter: true }) opatrně; může nečekaně upravit schémata.
Místo toho upřednostňujte explicitní migrace, které jasně definují každou změnu schématu. Pro porovnání vašich modelů se skutečnou strukturou databáze použijte:
await queryInterface.describeTable('tableName');To pomáhá odhalit nesoulady, než ovlivní výrobu.
4. Chyby dotazu a vypršení časového limitu
Problém: Vidíte chyby související s časovým limitem, jako například Connection timeout nebo Too many connections.
Jak opravit:
Problémy s časovým limitem jsou často způsobeny vyčerpanými spojovacími poli nebo nezavřenými připojeními. Ujistěte se, že všechny dotazy Sequelize jsou správně čekány, aby se po použití připojení vrátila zpět do poolu.
Také můžete doladit konfiguraci poolu v Sequelize, aby lépe vyhovovala zátěži vaší aplikace:
const sequelize = new Sequelize(DB_NAME, DB_USER, DB_PASSWORD, {
host: DB_HOST,
dialect: 'mysql',
pool: {
max: 10,
min: 0,
acquire: 30000,
idle: 10000
}
});Pokud vaše aplikace obsluhuje mnoho současných uživatelů, zvažte zvýšení parametru MySQL max_connections ve vaší konfiguraci databáze. Sledujte aktivní spojení pomocí SHOW PROCESSLIST; v MySQL, abyste odhalili úniky nebo nepoužívané relace.
5. Pomalé provádění dotazu
Problém: Některé dotazy trvají výrazně déle, než se očekávalo, což způsobuje pomalé odpovědi API nebo vysokou latenci.
Jak diagnostikovat:
Začněte tím, že identifikujete, které dotazy jsou pomalé. Můžete zaznamenat všechny dotazy, které Sequelize provádí, tím, že dočasně povolíte logování:
const sequelize = new Sequelize(..., { logging: console.log });Poté použijte příkaz EXPLAIN v MySQL, abyste pochopili, jak databáze vykonává dotaz:
EXPLAIN SELECT * FROM users WHERE email = 'user@example.com';Pokud výstup ukazuje „full table scan“, dotazu chybí index.
Můžete také povolit log pomalých dotazů MySQL, který automaticky zaznamenává pomalé operace:
SET GLOBAL slow_query_log = 'ON';
SET GLOBAL long_query_time = 1;Jak opravit:
Přidejte indexy k často dotazovaným sloupcům (zejména těm, které se používají v klauzulích WHERE, JOIN a ORDER BY). Vyhněte se SELECT *, místo toho explicitně načtěte pouze pole, která potřebujete, pomocí možnosti attributes.
Pokud Sequelize generuje neefektivní dotazy s zbytečnými spojeními, přepište dotaz pomocí čistého SQL. U velkých reportů nebo analytických dotazů je rozdělte na menší kroky nebo použijte nástroje pro ukládání do mezipaměti, například Redis, pro uchování opakujících se výsledků.
6. Zablokování a chyby souběžného zpracování
Problém: Objevují se vám chyby jako Deadlock found when trying to get lock; try restarting transaction, zejména při vysokém zatížení.
Jak diagnostikovat:
Zkontrolujte stav InnoDB v MySQL, abyste zjistili, které dotazy nebo tabulky byly zapojeny:
SHOW ENGINE INNODB STATUS\GTento výstup obsahuje podrobné informace o nedávných zámcích a čekáních na zámky. Můžete také povolit obecné nebo transakční záznamy, abyste mohli zkontrolovat sled dotazů vedoucích k problému.
Jak opravit:
Zamčení nastávají, když dvě nebo více transakcí čekají na zámky druhé. Aby se minimalizovala:
Udržujte transakce co nejkratší. Nepřistupujte k externím službám ani nevykonávejte náročné výpočty během držení zámku.
Vždy přistupujte k tabulkám a řádkům ve stejném pořadí napříč transakcemi, abyste se vyhnuli vzájemnému blokování.
Pro opakující se zablokování implementujte jednoduchý mechanismus opětovného pokusu s exponenciálním zpožděním:
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; } } }Používejte zámky na úrovni řádků (
SELECT ... FOR UPDATE) pouze tehdy, když je to nezbytné, a uvolňujte je okamžitě.Rozdělte velké transakce na menší části, aby se snížila konkurence.
Upravte úrovně izolace transakcí, pokud je to vhodné, ale pouze po potvrzení, že to neovlivní konzistenci dat.
Tipy pro optimalizaci výkonu
Problémy s výkonem často pramení z neefektivních dotazů, chybějících indexů nebo špatného zpracování připojení. Zde je několik praktických tipů, jak zlepšit výkon Sequelize, aniž byste obětovali přehlednost nebo udržovatelnost.
1. Optimalizujte dotazy
Pište dotazy tak, aby vyžadovaly pouze to, co je potřeba. Načítání zbytečných dat zvyšuje využití paměti a zpomaluje odpovědi. Použijte attributes k omezení polí:
const users = await User.findAll({ attributes: ['id', 'name'] });Vždy filtrovat výsledky pomocí indexovaných sloupců a pokud možno se vyhnout širokým vyhledáváním, jako je LIKE '%term%'.
2. Efektivně používejte indexy
Indexy urychlují vyhledávání, ale mohou zpomalit zápisy. Přidávejte indexy pouze tam, kde přinášejí měřitelné výhody. Prozkoumejte výkon dotazů pomocí MySQL EXPLAIN, abyste ověřili zlepšení před a po přidání indexu:
await queryInterface.addIndex('users', ['email']);3. Nastavte připojovací pool
Pool připojení určuje, kolik databázových připojení Sequelize udržuje.
- Pro malé aplikace je obvykle dostačující 5–10 připojení.
- U vysoce zatížených systémů zvýšte velikost poolu a upravte časové limity, abyste předešli zácpám v připojení. Pravidelně sledujte využití pomocí příkazu MySQL
SHOW PROCESSLIST;.
4. Povolit protokolování a sledování
Dočasně zapněte logování Sequelize, abyste si mohli prohlédnout SQL dotazy. Použijte pomalý log dotazů MySQL k identifikaci dotazů, které překračují váš výkonový limit. Pro sledování v reálném čase integrujte monitorovací nástroje, jako jsou PM2, New Relic nebo Datadog, k měření latence a využití zdrojů.
5. Ukládání častých dotazů do mezipaměti
Ukládejte do mezipaměti výsledky pro data, která se často nemění. Nástroje jako Redis nebo Memcached snižují zátěž databáze a zlepšují dobu odezvy, zejména u zátěže s převahou čtení.
6. Stránkovat výsledky
Velké množství výsledků spotřebovává značné množství paměti. Vždy stránkujte dotazy v API:
const users = await User.findAll({ limit: 50, offset: 100 });Stránkování udržuje odpovědi lehké a konzistentní při zátěži.
7. Používejte surové dotazy pro složité operace
Pokud abstrakce Sequelize vede k neefektivnímu SQL pro konkrétní případ použití, proveďte přímo dotaz v surovém SQL:
const [results] = await sequelize.query('SELECT name FROM users WHERE active = 1');Používejte surové dotazy střídmě a jasně je dokumentujte pro budoucí údržbu.
Často kladené otázky
1. Co je Sequelize v Node.js?
Sequelize je objektově-relační mapper (ORM) pro Node.js, který poskytuje vysoce úrovňové, na JavaScriptu založené API pro práci s SQL databázemi jako MySQL, PostgreSQL, SQLite a MariaDB. Místo psaní surového SQL pro každou operaci definujete modely, které se mapují na databázové tabulky, a používáte metody modelů pro vložení, dotaz, aktualizaci a mazání záznamů. Sequelize také podporuje asociace (vztahy mezi modely), transakce, migrace a surové dotazy, když potřebujete přímé SQL.
2. Jak připojím Sequelize k MySQL?
Chcete-li připojit Sequelize k MySQL, vytvoříte instanci Sequelize s údaji o vaší databázi a nastavením. V souboru Node.js vyžádejte Sequelize, volitelně načtěte proměnné prostředí a poté jej vytvořte s názvem databáze, uživatelským jménem, heslem a možnostmi hostitele/dialektu. Například:
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!');Vždy uchovávejte přihlašovací údaje mimo správu zdrojového kódu (například v souboru .env nebo v správci tajemství).
3. Jak vytvářím a synchronizuji modely v Sequelize?
V Sequelize modely představují tabulky. Definujete je pomocí sequelize.define() nebo rozšířením třídy Model. Poté je můžete synchronizovat s vaší databází, takže Sequelize vytvoří tabulky automaticky (skvělé pro vývoj). Zde je malý příklad:
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();Pro produkční prostředí je lepší používat migrace, abyste měli verzi změn schématu pod kontrolou.
4. Jak používám Sequelize s Expressem?
V aplikaci Express inicializujte Sequelize v samostatném souboru (například db.js), exportujte připojenou instanci a modely a importujte je tam, kde je potřebujete ve svých route handlerech nebo controllerech. V route handlerech používejte async/await pro volání metod modelů Sequelize a chyby ošetřujte pomocí try/catch nebo middleware pro chyby. Takto to v praxi vypadá:
// 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);
});Ujistěte se, že provedete migrace nebo zavoláte sequelize.sync() před spuštěním vašeho Express serveru, aby tabulky vaší databáze existovaly, když přijdou požadavky.
5. Jaký je rozdíl mezi Sequelize a čistými SQL dotazy?
Sequelize vám umožňuje psát databázovou logiku v JavaScriptu, zatímco čisté SQL znamená psát SQL příkazy přímo. Sequelize činí váš kód přehlednějším a snáze udržovatelným, protože můžete definovat modely a vztahy jednou a používat je napříč aplikací. Čisté SQL vám dává větší kontrolu a může být někdy rychlejší pro velmi složité dotazy.
Stručně řečeno, používejte Sequelize pro většinu běžných úkolů a syrový SQL, když potřebujete doladit výkon nebo spustit něco, co Sequelize nedokáže snadno vyjádřit.
6. Jak mohu definovat asociace v Sequelize?
Sequelize usnadňuje popisování vztahů mezi tabulkami. Můžete nastavit vztahy jeden na jednoho, jeden na mnoho nebo mnoho na mnoho pomocí jednoduchých metod jako hasOne, hasMany a belongsToMany. Například:
// 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' });Jakmile je definováno, můžete ve svých dotazech použít include k automatickému načtení souvisejících dat.
7. Jak mám řešit migrace a změny schématu?
Ve vývoji můžete použít sequelize.sync() k rychlému vytvoření tabulek. Ale v produkci byste měli vždy používat migrace. Migrace jsou verzované soubory, které popisují, jak se časem mění schéma vaší databáze, podobně jako Git commity sledují změny v kódu.
Můžete vytvořit migraci pomocí Sequelize CLI:
npx sequelize-cli migration:generate --name add-users-tableKaždá migrace má metody up a down, jednu pro aplikaci změny a jednu pro její vrácení. Spusťte své migrace s:
npx sequelize-cli db:migrateTímto způsobem má každý ve vašem týmu (a při každém nasazení) stejnou strukturu databáze.
Pro rychlé testování použijte sequelize.sync(), ale jakmile je vaše aplikace v provozu, držte se migrací, protože jsou bezpečnější, vratné a snadněji sledovatelné.
Závěr
V tomto tutoriálu jste nastavili Sequelize s Node.js a MySQL k správě dat pomocí modelů, asociací a migrací. Také jste zabezpečili přihlašovací údaje k databázi pomocí proměnných prostředí a prozkoumali nejlepší postupy pro řešení problémů a optimalizaci výkonu.
S těmito kroky nyní máte pevný základ pro vytváření a udržování bezpečných a efektivních aplikací v Node.js, které používají Sequelize a MySQL pro správu dat.
Chcete-li se dozvědět více o Sequelize, podívejte se na dokumentaci produktu. Pro další podobné návody na Node.js si prohlédněte následující články:
- Jak nastavit GraphQL server v Node.js s Apollo Server a Sequelize
- Jak implementovat caching v Node.js pomocí Redis
- Jak vytvořit webový server v Node.js pomocí modulu HTTP
Děkujeme, že se učíte s komunitou Linux-Console.net.
