Express: migratsiya va seed
Bazani ulash darsida jadval db/index.js ichida,
CREATE TABLE IF NOT EXISTS bilan yaratildi. Ilova yolg’iz ishlaganda bu
yetadi. Endi tasavvur qiling: vazifaga “muhimlik darajasi” ustunini
qo’shmoqchisiz. CREATE TABLE ni tahrirlaysiz — lekin jadval allaqachon
mavjud, IF NOT EXISTS uni chetlab o’tadi va yangi ustun paydo bo’lmaydi.
Hamkasbingizning kompyuterida esa jadval yo’q edi, unda yangi ustun bilan yaratiladi. Ikki mashinada ikki xil baza.
Migratsiya nima
Asosiy g’oya: baza tuzilishi ham kod, va u ham git da saqlanadi. Yangi
dasturchi loyihani klonlab, bitta buyruq yuritadi va bazasi hammanikiga
mos bo’ladi.
| Yondashuv | Muammo |
|---|---|
Qo’lda CREATE TABLE yozish |
Har mashinada boshqacha baza |
| SQL ni chatda yuborish | Kim bajardi, kim bajarmadi — noma’lum |
| Migratsiya fayllari | Tarix git da, bajarilgani bazada qayd etilgan |
Ulanishni soddalashtirish
Jadval yaratish endi migratsiyaning ishi, shuning uchun db/index.js
faqat ulanish bilan qoladi:
// db/index.js
const path = require("path");
const { DatabaseSync } = require("node:sqlite");
const databasePath = path.join(__dirname, "..", "tasks.db");
const database = new DatabaseSync(databasePath);
module.exports = database;
CREATE TABLE qatorlari o’chdi. Bu muhim chegara: ilova ishga
tushganda baza tuzilishini o’zgartirmaydi. Tuzilishni faqat siz,
ataylab, npm run migrate bilan o’zgartirasiz.
Birinchi migratsiya
mkdir migrations
migrations/001-create-tasks.js:
// migrations/001-create-tasks.js
module.exports = {
name: "001-create-tasks",
up(database) {
database.exec(`
CREATE TABLE IF NOT EXISTS tasks (
id INTEGER PRIMARY KEY AUTOINCREMENT,
title TEXT NOT NULL,
is_done INTEGER NOT NULL DEFAULT 0,
created_at TEXT NOT NULL DEFAULT (datetime('now'))
)
`);
},
};
Fayl nomidagi 001 — tartib raqami. Migratsiyalar ketma-ketligi
muhim: ustun qo’shishdan oldin jadval mavjud bo’lishi kerak.
up funksiyasining nomi ham konvensiya: “tuzilishni oldinga surish”
degani. Ba’zi tizimlarda down ham bo’ladi — o’zgarishni qaytarish
uchun.
Migratsiyalarni bajaruvchi skript
migrate.js — loyiha ildizida:
// migrate.js
const fs = require("fs");
const path = require("path");
const database = require("./db");
// Bajarilgan migratsiyalar shu jadvalda qayd etiladi
database.exec(`
CREATE TABLE IF NOT EXISTS migrations (
name TEXT PRIMARY KEY,
run_at TEXT NOT NULL DEFAULT (datetime('now'))
)
`);
const migrationsDir = path.join(__dirname, "migrations");
const files = fs
.readdirSync(migrationsDir)
.filter((file) => file.endsWith(".js"))
.sort();
const isApplied = database.prepare("SELECT name FROM migrations WHERE name = ?");
const markApplied = database.prepare("INSERT INTO migrations (name) VALUES (?)");
let appliedCount = 0;
for (const file of files) {
const migration = require(path.join(migrationsDir, file));
if (isApplied.get(migration.name)) {
console.log("O'tkazib yuborildi:", migration.name);
continue;
}
migration.up(database);
markApplied.run(migration.name);
appliedCount = appliedCount + 1;
console.log("Bajarildi:", migration.name);
}
console.log(`Jami yangi migratsiya: ${appliedCount}`);
Skript uch ishni bajaradi: migrations jadvalini tayyorlaydi, papkadagi
fayllarni tartib bilan o’qiydi, bajarilmaganini ishga tushirib qayd
etadi. fs.readdirSync va path.join
fayl bilan ishlash darsida ko’rilgan.
package.json ga buyruq qo’shing:
{
"scripts": {
"start": "node app.js",
"dev": "nodemon app.js",
"migrate": "node migrate.js",
"seed": "node seed.js"
}
}
npm run migrate
Bajarildi: 001-create-tasks
Jami yangi migratsiya: 1
Qayta yurgizing:
npm run migrate
O'tkazib yuborildi: 001-create-tasks
Jami yangi migratsiya: 0
Ikkinchi marta hech narsa bajarilmadi — migrations jadvalida yozuv bor.
Buyruqni xohlagancha takrorlash xavfsiz.
Ikkinchi migratsiya: ustun qo’shish
Endi haqiqiy o’zgarish qilamiz. migrations/002-add-priority.js:
// migrations/002-add-priority.js
module.exports = {
name: "002-add-priority",
up(database) {
database.exec(
"ALTER TABLE tasks ADD COLUMN priority INTEGER NOT NULL DEFAULT 3"
);
},
};
npm run migrate
O'tkazib yuborildi: 001-create-tasks
Bajarildi: 002-add-priority
Jami yangi migratsiya: 1
Birinchi migratsiya chetlab o’tildi, ikkinchisi bajarildi. Jadvalda
allaqachon ma’lumot bo’lsa, ular yo’qolmaydi: eski qatorlar priority
ustuniga 3 qiymatini oladi — DEFAULT shuni aytadi.
Modelga yangi ustunni qo’shish
Baza o’zgardi, endi model qatlami ham bilishi
kerak. models/task.js dagi toTask ga bitta qator qo’shiladi:
function toTask(row) {
return {
id: row.id,
title: row.title,
isDone: row.is_done === 1,
priority: row.priority,
createdAt: row.created_at,
};
}
Model qatlami shu yerda o’zini oqlaydi: butun ilovada priority bitta
faylda paydo bo’ldi, marshrutlarga qo’l tegmadi.
Seed — sinov ma’lumoti
Bo’sh baza bilan ishlash noqulay: har sinovda qo’lda vazifa qo’shasiz.
seed.js:
// seed.js
const database = require("./db");
const sampleTasks = [
{ title: "Express o'rganish", isDone: true, priority: 1 },
{ title: "Bazani ulash", isDone: true, priority: 2 },
{ title: "Migratsiya yozish", isDone: false, priority: 1 },
{ title: "Testlarni yozish", isDone: false, priority: 4 },
];
// Eski sinov ma'lumotini tozalaymiz
database.exec("DELETE FROM tasks");
database.exec("DELETE FROM sqlite_sequence WHERE name = 'tasks'");
const insert = database.prepare(
"INSERT INTO tasks (title, is_done, priority) VALUES (?, ?, ?)"
);
for (const task of sampleTasks) {
insert.run(task.title, task.isDone ? 1 : 0, task.priority);
}
const count = database.prepare("SELECT COUNT(*) AS total FROM tasks").get();
console.log(`Seed tugadi. Jadvalda ${count.total} ta vazifa bor.`);
npm run seed
Seed tugadi. Jadvalda 4 ta vazifa bor.
Skriptni qancha yursangiz ham natija bir xil: eski yozuvlar o’chadi,
o’sha to’rttasi qayta qo’shiladi. DELETE FROM sqlite_sequence qatori
id sanagichini nolga qaytaradi — usiz har npm run seed dan keyin
raqamlar 5, 6, 7 deb davom etardi.
Tekshiring:
curl http://localhost:3000/api/tasks
[{"id":1,"title":"Express o'rganish","isDone":true,"priority":1,"createdAt":"2026-09-12 14:04:41"},{"id":2,"title":"Bazani ulash","isDone":true,"priority":2,"createdAt":"2026-09-12 14:04:41"},{"id":3,"title":"Migratsiya yozish","isDone":false,"priority":1,"createdAt":"2026-09-12 14:04:41"},{"id":4,"title":"Testlarni yozish","isDone":false,"priority":4,"createdAt":"2026-09-12 14:04:41"}]
Yangi dasturchining yo’li
Migratsiya tizimining butun qiymati shu uch buyruqda ko’rinadi:
npm install
npm run migrate
npm run seed
Baza fayli git da yo’q, lekin uni tiklash uchun hech kimdan hech narsa
so’ramaysiz. Tuzilish migrations/ da, sinov ma’lumoti seed.js da —
ikkalasi ham repozitoriyda.
Serverda esa npm run seed tushirilmaydi, faqat npm run migrate
bajariladi: tuzilish yangilanadi, ma’lumot tegilmaydi.
| Muhit | migrate |
seed |
|---|---|---|
| Kompyuteringiz | Ha | Ha |
| Sinov serveri | Ha | Ha |
| Ishlab turgan server | Ha | Yo’q |
Amaliy mashq
task-app loyihasida davom eting:
db/index.jsdanCREATE TABLEni olib tashlab, unimigrations/001-create-tasks.jsga ko’chiring;migrate.jsni yozing vanpm run migrateni ikki marta yurgizib, ikkinchisida hech narsa bajarilmasligini ko’ring;002-add-priority.jsni yozib,ALTER TABLEbilan yangi ustun qo’shing;migrationsjadvalidan002qatorini qo’lda o’chirib (DELETE FROM migrations WHERE name = '002-add-priority'),npm run migrateni qayta yurgizing vaduplicate column namexatosini o’z ko’zingiz bilan ko’ring;toTaskgapriorityni qo’shib,curljavobida ko’rinishini tasdiqlang;seed.jsyozib, uni ikki marta yurgizing — vazifalar soni har safar to’rtta bo’lib qolishi kerak.
4-qadam noqulay ko’rinadi, lekin aynan u migratsiya jadvali nimani himoya qilishini ko’rsatadi.
Qisqacha xulosa
- Jadvalni ilova ishga tushganda yaratish turli mashinalarda turli baza tuzilishiga olib keladi.
- Migratsiya — raqamlangan, bir marta bajariladigan tuzilish o’zgarishi; seed — ma’lumot to’ldirish.
- Bajarilgan migratsiya nomi bazadagi
migrationsjadvalida qayd etiladi va shuning uchun takroran bajarilmaydi. - Fayl nomi
001,002shaklida raqamlanadi — alifbo tartibi to’g’ri ishlashi uchun. - Bajarilgan migratsiya tahrirlanmaydi — har o’zgarish uchun yangi fayl yoziladi.
ALTER TABLE ... ADD COLUMNdaIF NOT EXISTSyo’q, ikkinchi urinishduplicate column namexatosini beradi.seedishlab turgan serverda yurgizilmaydi — u bor ma’lumotni o’chiradi.
Keyingi darsda sessiya va cookie — server kim kelganini qanday eslab qolishi.