6.11-bob: ORM — Sequelize (model, relations, migration)
6-QISM — Ma'lumotlar bazasi (Database) · 11-mavzu
1. Kirish va motivatsiya
Xom SQL'ni (6.4–6.10) chuqur o'rgandik — bu poydevor. Endi ORM (Object-Relational Mapping) ga o'tamiz: SQL'ni JavaScript obyektlari bilan ishlash. ORM — relatsion DB jadvallari va qatorlarini JS class va obyektlariga moslashtiruvchi qatlam. SQL yozish o'rniga, User.findByPk(1) deysiz — ORM uni SQL'ga aylantiradi, bajaradi, va natijani JS obyekti qilib qaytaradi. Bu — produktivlikni keskin oshiradi.
Sizning stack'ingizda uchta ORM bor: Sequelize (klassik, keng tarqalgan — bu bob), Prisma (zamonaviy, type-safe — 6.12), TypeORM (NestJS bilan mashhur — 6.13). Sequelize — eng qadimiy va keng ishlatiladigani; ko'p mavjud loyihada bor. U MySQL, PostgreSQL, SQLite, SQL Server bilan ishlaydi (DB'ni almashtirsangiz, kod deyarli o'zgarmaydi — abstraksiya).
Muhim: ORM SQL'ni almashtirmaydi — uning ustida ishlaydi. Shuning uchun biz avval SQL'ni o'rgandik (6.4-6.10). ORM qulay, lekin u ham SQL generatsiya qiladi; N+1 (6.10: 2.11), indeks, tranzaksiya — bularning hammasi ORM'da ham bor. SQL'ni bilmasdan ORM ishlatish — "qora quti"ga ishonish (sekin so'rov, xato — tushunmaysiz). Bu bob: Sequelize bilan model, bog'lanishlar (associations), so'rovlar, tranzaksiya, migration va seeding — chuqur.
O'xshatish: xom SQL — xorijiy tilda gaplashish (DB tilini bevosita bilasiz — kuchli, lekin har gapni o'zingiz tuzasiz). ORM — tarjimon orqali gaplashish: siz ona tilingizda (JS) aytasiz, tarjimon (ORM) DB tiliga (SQL) o'giradi. Tez, qulay — lekin tarjimon ba'zan noqulay so'zlaydi (sekin SQL). Yaxshi natija uchun ikkala tilni ham bilish kerak (SQL + ORM).
Nega muhim?
- Produktivlik — SQL yozish o'rniga JS obyektlari (tez yozish).
- Stack talabi — Sequelize/Prisma/TypeORM uchchovi ham sizning stack'ingizda.
- DB abstraksiyasi — DB'ni almashtirish oson (MySQL PostgreSQL).
- Migration — schema o'zgarishini nazorat ostida boshqarish.
2. Nazariya — chuqur tushuntirish
2.1. ORM nima va nega (under the hood)
ORM — DB jadvallarini obyektlarga moslaydi (sequelize.org):
Jadval (users) Model (User class)
Qator (row) Instance (obyekt)
Ustun (column) Property (xususiyat)
Siz yozasiz: await User.findByPk(1)
ORM qiladi: SELECT * FROM users WHERE id = 1 JS obyekt qaytaradiORM ishi: sizning JS chaqiruvingizni SQL'ga aylantiradi, bajaradi, natijani obyektga o'giradi. Siz SQL ko'rmaysiz (lekin u bor!). Foydasi: tezroq yozasiz, DB-agnostik, xavfsiz (parametrli — 6.4: 2.15 avtomatik). Kamchiligi: yashirin SQL (sekin bo'lishi mumkin — 2.14).
2.2. ORM afzalliklari va kamchiliklari
Afzallik:
- Tez yozish (SQL o'rniga JS)
- DB-agnostik (MySQL PostgreSQL almashtirish oson)
- Xavfsiz (parametrli so'rov avtomatik — injection himoyasi — 14)
- Migration, validatsiya, hook, bog'lanish — tayyor
- Type-safety (Prisma/TypeORM — TS bilan)
Kamchilik:
- Yashirin SQL (sekin so'rov — N+1 — 2.14)
- Murakkab so'rov qiyin (window/CTE — ko'pincha xom SQL — 6.7)
- O'rganish (ORM API + baribir SQL bilim kerak)
- "Sehrli" xatti-harakat (debug qiyin)Konsensus: ORM kundalik CRUD uchun a'lo (tez, xavfsiz). Murakkab analitik so'rov uchun — xom SQL 6.7-bob yoki query builder. SQL bilimi shart (ORM uni yashiradi, lekin yo'qotmaydi).
2.3. Sequelize o'rnatish va ulanish
npm install sequelize # ORM
npm install pg pg-hstore # PostgreSQL driver (yoki mysql2 — MySQL)import { Sequelize } from "sequelize";
const sequelize = new Sequelize(process.env.DATABASE_URL, { // (5.8)
dialect: "postgres", // yoki "mysql"
logging: false, // SQL log (dev'da true — SQL ko'rish)
pool: { max: 10, idle: 30000 }, // connection pool (6.5: 2.5)
});
await sequelize.authenticate(); // ulanishni tekshirish
dialect— qaysi DB (postgres/mysql/sqlite). Sequelize shu DB'ning driver'ini ishlatadi.logging: true(dev) — generatsiya qilingan SQL'ni ko'rsatadi (ORM nima qilayotganini tushunish uchun muhim — 2.14).pool— connection pool 6.5-bob.
2.4. Model ta'rifi (jadval)
Model — jadvalni ifodalovchi class (sequelize.org):
import { DataTypes } from "sequelize";
const User = sequelize.define("User", { // "User" "Users" jadval
id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true },
ism: { type: DataTypes.STRING, allowNull: false }, // NOT NULL (6.4)
email: { type: DataTypes.STRING, unique: true, allowNull: false, validate: { isEmail: true } },
yosh: { type: DataTypes.INTEGER, validate: { min: 18 } }, // validatsiya (2.6)
rol: { type: DataTypes.ENUM("user", "admin"), defaultValue: "user" },
}, {
timestamps: true, // createdAt, updatedAt avtomatik (6.2)
// tableName: "users", paranoid: true (soft delete)
});DataTypes — SQL turlari (STRINGVARCHAR, INTEGER, BOOLEAN, DATE, ENUM, JSONB — 6.4: 2.3). Har maydonga: tur + cheklovlar (allowNull, unique, defaultValue) + validate 2.6-bob.
timestamps— createdAt/updatedAt avtomatik. Model nomi jadval (ko'plik).
Ikki uslub: yuqoridagi
sequelize.define(...)— funksional (qisqa, keng tarqalgan). Muqobil — class-based:class User extends Model {}va so'ngUser.init({...maydonlar}, { sequelize, modelName: "User" }). Ikkisi ham bir xil natija beradi;inituslubi TypeScript va model'ga maxsus metod qo'shishda qulayroq 2.13-bob. Bu bobdadefineuslubidan foydalanamiz.
2.5. CRUD (model metodlari)
// CREATE
const user = await User.create({ ism: "Ali", email: "ali@a.uz" });
// READ
await User.findAll(); // hammasi (SELECT *)
await User.findByPk(1); // PK bo'yicha (WHERE id=1)
await User.findOne({ where: { email: "ali@a.uz" } }); // shartli
await User.findAll({ where: { yosh: { [Op.gt]: 18 } } }); // operator (2.7)
// UPDATE
await user.update({ yosh: 26 }); // instance
await User.update({ yosh: 26 }, { where: { id: 1 } }); // to'g'ridan
// DELETE
await user.destroy(); // instance
await User.destroy({ where: { id: 1 } }); // to'g'ridanSequelize ikki uslub: instance (
user.update) va static (User.update({...}, {where})).findByPk(PK),findOne(bitta),findAll(ko'p). MongoDB 6.2-bob bilan o'xshash, lekin SQL ustida.
2.6. Validatsiya va hook
const User = sequelize.define("User", {
email: { type: DataTypes.STRING, validate: { isEmail: true } }, // built-in
parol: { type: DataTypes.STRING, validate: { len: [8, 100] } }, // uzunlik
}, {
hooks: {
beforeCreate: async (user) => { // saqlashdan oldin (6.2: 2.16)
user.parol = await bcrypt.hash(user.parol, 12); // parol hash (5.15)
},
},
});Validatsiya (5.9, 6.2: 2.5 — DB darajasida):
isEmail,len,min/max,notEmpty, custom. Hook (lifecycle):beforeCreate,afterUpdate— parol hash, slug. Mongoose'dagi 6.2-bob ekvivalent.
2.7. Operatorlar (Op)
import { Op } from "sequelize";
await User.findAll({
where: {
yosh: { [Op.gt]: 18 }, // > 18
rol: { [Op.in]: ["admin", "moderator"] }, // IN
ism: { [Op.like]: "Al%" }, // LIKE
[Op.or]: [{ vip: true }, { yosh: { [Op.gte]: 60 } }], // OR
},
order: [["yosh", "DESC"]], // ORDER BY (6.4: 2.10)
limit: 10, offset: 20, // sahifalash
attributes: ["ism", "email"], // SELECT ustunlar (6.4)
});
Op— SQL operatorlari (Op.gt,Op.in,Op.like,Op.or— 6.4: 2.9). MongoDB query operatorlariga (6.2: 2.8) o'xshash.order/limit/offset/attributes— so'rovni sozlash.
2.8. Associations (bog'lanishlar) — eng muhim
Sequelize bog'lanishlari (sequelize.org):
One-to-One: hasOne + belongsTo
One-to-Many: hasMany + belongsTo
Many-to-Many: belongsToMany (ikki tomondan, junction jadval)// One-to-Many: User ko'p Order (6.1: 2.5)
User.hasMany(Order, { foreignKey: "userId" }); // user'ning ko'p buyurtmasi
Order.belongsTo(User, { foreignKey: "userId" }); // buyurtma bir user'nikiIkki tomonlama ta'rif:
hasMany(user tomoni) +belongsTo(order tomoni) — birga. Sequelize FK (userId) ni avtomatik yaratadi/ishlatadi (6.1: 2.5). Bu — bog'lanishning asosi; keyinincludebilan birga olinadi 2.9-bob.
2.9. Eager loading (include — JOIN)
Include — bog'langan ma'lumotni birga olish (JOIN — 6.7, MongoDB populate — 6.2: 2.13):
// User + uning buyurtmalari (bitta so'rovda — JOIN)
const user = await User.findByPk(1, {
include: [{ model: Order }], // buyurtmalarni ham (eager)
});
console.log(user.Orders); // buyurtmalar massivi
// Nested include + shart
await User.findAll({
include: [{
model: Order,
where: { holat: "tugallandi" }, // faqat tugallangan buyurtmalar
include: [{ model: Product }], // ichma-ich (buyurtma mahsulot)
}],
});
include= JOIN (eager loading): bog'langan ma'lumotni bitta so'rovda oladi (N+1 oldini oladi — 2.14, 6.10: 2.11). Lekin ortiqcha include — murakkab, sekin so'rov (manba). Faqat kerakli ma'lumotni include qiling.
2.10. Tranzaksiya
const t = await sequelize.transaction(); // tranzaksiya (6.5: 2.9, 6.9)
try {
await Account.update({ balans: ... }, { where: { id: 1 }, transaction: t }); // t!
await Account.update({ balans: ... }, { where: { id: 2 }, transaction: t });
await t.commit(); // saqla
} catch (err) {
await t.rollback(); // bekor
throw err;
}
// Managed transaction (avtomatik commit/rollback — afzal)
await sequelize.transaction(async (t) => {
await Account.update({...}, { transaction: t });
await Account.update({...}, { transaction: t });
// xato bo'lsa — avtomatik rollback; muvaffaqiyat — commit
});Har amalga
{ transaction: t }bering (aks holda tranzaksiyadan tashqarida — 6.9: 2.9). Managed transaction (callback) — afzal: commit/rollback avtomatik (unutilmaydi). Tranzaksiya — pul, ko'p yozuv (6.9 ACID).
2.11. Migration (schema o'zgarishini nazorat)
Migration — DB schema o'zgarishini versiyalangan, qaytariladigan fayllar bilan boshqarish (sequelize-cli):
Migration nima uchun:
- Schema o'zgarishi (jadval/ustun qo'shish) NAZORAT ostida (git'da — 4)
- Jamoa/muhitlar SINXRON (har kim bir xil schema)
- QAYTARILADIGAN (up — qo'llash; down — bekor qilish)
- Production'da xavfsiz (qo'lda ALTER emas — 6.4: 2.13)// migrations/xxxx-create-users.js
export async function up(queryInterface, Sequelize) {
await queryInterface.createTable("Users", { // jadval yaratish
id: { type: Sequelize.INTEGER, primaryKey: true, autoIncrement: true },
ism: { type: Sequelize.STRING, allowNull: false },
createdAt: Sequelize.DATE, updatedAt: Sequelize.DATE,
});
}
export async function down(queryInterface) {
await queryInterface.dropTable("Users"); // bekor qilish (qaytarish)
}Migration MAJBURIY (production — manba): schema'ni qo'lda o'zgartirmang (6.4: 2.13). Har o'zgarish — migration fayl (git'da — 4, versiyalangan).
up(qo'llash),down(qaytarish).sequelize-clibilan boshqariladi (db:migrate,db:migrate:undo). Bu — jamoa va muhitlarni sinxron tutadi.
2.12. Seeding (boshlang'ich ma'lumot)
Seed — DB'ga boshlang'ich/test ma'lumot solish (sequelize):
// seeders/xxxx-demo-users.js
export async function up(queryInterface) {
await queryInterface.bulkInsert("Users", [
{ ism: "Admin", email: "admin@a.uz", createdAt: new Date(), updatedAt: new Date() },
{ ism: "Test", email: "test@a.uz", createdAt: new Date(), updatedAt: new Date() },
]);
}
export async function down(queryInterface) {
await queryInterface.bulkDelete("Users", null, {});
}Seed — boshlang'ich ma'lumot (admin foydalanuvchi, kategoriyalar, test ma'lumoti). Dev/test uchun qulay (
db:seed:all). Migration'dan farqi: migration — tuzilma; seed — ma'lumot.
2.13. Model fayllar tuzilishi (loyiha)
models/
index.js — sequelize ulanish + barcha modellarni yuklash
user.js — User model + associate (bog'lanishlar)
order.js — Order model
migrations/ — schema o'zgarishlari
seeders/ — boshlang'ich ma'lumot
config/ — DB sozlamalari (dev/test/prod)Sequelize loyihasi shu tuzilmada (sequelize-cli generatsiya qiladi).
models/index.js— markaziy (ulanish + modellar + associate). Migration/seed — alohida papka.
2.14. ORM tuzog'i — N+1 va yashirin SQL
ORM'ning eng katta tuzog'i — N+1 (6.10: 2.11) va yashirin sekin SQL:
// N+1 (har user uchun alohida so'rov!)
const users = await User.findAll(); // 1 so'rov
for (const u of users) {
const orders = await u.getOrders(); // har user uchun (N so'rov!)
}
// Eager loading (include — 1 so'rov — 2.9)
const users = await User.findAll({ include: [Order] }); // JOINORM N+1'ni yashiradi (ko'rinmaydi, lekin sekin): tsiklda lazy loading (
getOrders) — N+1.include(eager) bilan oldini oling.logging: true2.3-bob bilan generatsiya qilingan SQL'ni ko'ring (necha so'rov?). SQL bilimi 6.10-bob shu yerda kerak.
2.15. Raw query (murakkab so'rov)
ORM murakkab so'rovni (window/CTE — 6.7) qiyin ifodalaydi xom SQL:
// Murakkab so'rov — raw query (parametrli — 14)
const [natija] = await sequelize.query(
"SELECT u.ism, RANK() OVER (ORDER BY SUM(o.summa) DESC) AS reyting FROM ...",
{ replacements: { sana: "2026-01-01" }, type: QueryTypes.SELECT } // parametrli
);ORM hamma narsani qila olmaydi (window functions, murakkab CTE — 6.7). Bunday holatda
sequelize.query(xom SQL) — parametrli (replacements— injection himoyasi — 14). ORM + xom SQL aralash — normal amaliyot.
2.16. Xavfsizlik va best practices (14)
Migration har doim (qo'lda ALTER emas — 2.11, 14)
Tranzaksiya ko'p yozuvda (managed — 2.10)
Eager loading (include) o'ylab — N+1 oldini oling, lekin ortiqcha emas (2.9, 2.14)
logging: true (dev) — SQL'ni ko'rib tekshiring (2.3, 2.14)
Validatsiya (model + API — 5.9); hook (parol hash — 2.6)
Raw query parametrli (replacements — 14, 2.15)
Maxfiy maydon (parol) — defaultScope: attributes exclude
Indeks (model'da indexes; migration'da — 6.10)3. Sintaksis — tez ma'lumotnoma
import { Sequelize, DataTypes, Op } from "sequelize";
const sequelize = new Sequelize(url, { dialect: "postgres" }); // (2.3)
const User = sequelize.define("User", { ism: DataTypes.STRING }, { timestamps: true }); // (2.4)
// CRUD (2.5)
await User.create({...}); await User.findByPk(1); await User.findAll({ where: {...} });
await user.update({...}); await user.destroy();
// Associations (2.8)
User.hasMany(Order); Order.belongsTo(User);
await User.findByPk(1, { include: [Order] }); // eager (2.9)
// Tranzaksiya 2.10-bob: sequelize.transaction(async (t) => {...})
// Migration 2.11-bob: up/down + sequelize-cli
// Operatorlar 2.7-bob: { [Op.gt]: 18 }4. Batafsil kod namunalari
Misol 1 — Ulanish (2.3)
// config/db.js
import { Sequelize } from "sequelize";
import { config } from "./index.js"; // (5.8)
import { logger } from "../utils/logger.js";
export const sequelize = new Sequelize(config.databaseUrl, {
dialect: "postgres",
logging: config.isProd ? false : (sql) => logger.debug(sql), // dev'da SQL log (2.14)
pool: { max: 10, min: 2, idle: 30000 }, // pool (6.5: 2.5)
});
export async function dbUlash() {
try {
await sequelize.authenticate();
logger.info(" Sequelize ulandi");
} catch (err) {
logger.error(" Ulanmadi:", err.message);
process.exit(1); // (5.8: fail fast)
}
}Misol 2 — Modellar (validatsiya, hook — 2.4, 2.6)
// models/user.js
import { DataTypes } from "sequelize";
import bcrypt from "bcrypt";
import { sequelize } from "../config/db.js";
export const User = sequelize.define("User", {
id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true },
ism: { type: DataTypes.STRING, allowNull: false, validate: { notEmpty: true } },
email: {
type: DataTypes.STRING, unique: true, allowNull: false,
validate: { isEmail: { msg: "Email noto'g'ri" } }, // (2.6)
},
parol: { type: DataTypes.STRING, allowNull: false, validate: { len: [8, 100] } },
rol: { type: DataTypes.ENUM("user", "admin"), defaultValue: "user" },
}, {
timestamps: true,
defaultScope: { attributes: { exclude: ["parol"] } }, // parolni qaytarma (14, 2.16)
hooks: {
beforeCreate: async (u) => { u.parol = await bcrypt.hash(u.parol, 12); }, // hash (5.15)
beforeUpdate: async (u) => {
if (u.changed("parol")) u.parol = await bcrypt.hash(u.parol, 12);
},
},
});
// Instance metod (parol solishtirish — 6.2: 2.17)
User.prototype.parolToOgri = function (p) { return bcrypt.compare(p, this.parol); };Misol 3 — Bog'lanishlar (associations — 2.8)
// models/index.js — associate
import { User } from "./user.js";
import { Order } from "./order.js";
import { Product } from "./product.js";
// One-to-Many: User Order (6.1: 2.5)
User.hasMany(Order, { foreignKey: "userId", as: "orders" });
Order.belongsTo(User, { foreignKey: "userId", as: "user" });
// Many-to-Many: Order Product (junction: OrderItems — 2.8)
Order.belongsToMany(Product, { through: "OrderItems", foreignKey: "orderId" });
Product.belongsToMany(Order, { through: "OrderItems", foreignKey: "productId" });
export { User, Order, Product };Misol 4 — CRUD service (2.5, 2.7)
import { Op } from "sequelize";
import { User } from "../models/index.js";
export const UserService = {
yarat: (data) => User.create(data), // hook parol hash (Misol 2)
topId: (id) => User.findByPk(id), // parolsiz (defaultScope — Misol 2)
emailTop: (email) => User.scope(null).findOne({ where: { email } }), // parol bilan (login — 5.15)
royxat: ({ page = 1, limit = 20, qidiruv, rol }) => {
const where = {};
if (rol) where.rol = rol;
if (qidiruv) where.ism = { [Op.iLike]: `%${qidiruv}%` }; // matn qidiruv (2.7)
return User.findAndCountAll({ // ma'lumot + umumiy son (sahifalash)
where, limit, offset: (page - 1) * limit, order: [["createdAt", "DESC"]],
});
},
yangila: async (id, data) => {
const user = await User.findByPk(id);
if (!user) return null;
return user.update(data); // hook (Misol 2)
},
ochir: (id) => User.destroy({ where: { id } }),
};Misol 5 — Eager loading (include — 2.9)
// Buyurtma + user + mahsulotlar (bitta so'rovda — JOIN — 2.9)
export const buyurtmaToliq = (id) => Order.findByPk(id, {
include: [
{ model: User, as: "user", attributes: ["ism", "email"] }, // user (kerakli ustunlar)
{ model: Product, through: { attributes: ["miqdor", "narx"] } }, // mahsulotlar (junction)
],
});
// User + faqat tugallangan buyurtmalari (shartli include — 2.9)
export const userFaolBuyurtmalar = (userId) => User.findByPk(userId, {
include: [{ model: Order, as: "orders", where: { holat: "tugallandi" }, required: false }],
});
// required: false LEFT JOIN (buyurtmasi yo'q bo'lsa ham user chiqadi — 6.7: 2.3)Misol 6 — Tranzaksiya (managed — 2.10)
import { sequelize } from "../config/db.js";
// Buyurtma yaratish — atomik (managed transaction — 2.10, 6.9)
export async function buyurtmaYarat(userId, items) {
return sequelize.transaction(async (t) => { // managed (avtomatik commit/rollback)
// 1. Buyurtma yarat
const order = await Order.create({ userId, holat: "yangi" }, { transaction: t });
// 2. Har mahsulot — zaxira tekshir va kamaytir (atomik)
for (const item of items) {
const product = await Product.findByPk(item.productId, {
transaction: t, lock: t.LOCK.UPDATE, // FOR UPDATE (6.9: 2.13)
});
if (product.zaxira < item.miqdor) {
throw new Error("Zaxira yetarli emas"); // avtomatik ROLLBACK
}
product.zaxira -= item.miqdor;
await product.save({ transaction: t });
await OrderItem.create(
{ orderId: order.id, productId: item.productId, miqdor: item.miqdor, narx: product.narx },
{ transaction: t }
);
}
return order; // muvaffaqiyat avtomatik COMMIT
});
}Misol 7 — Migration (2.11)
// migrations/20260101-create-users.js
export async function up(queryInterface, Sequelize) {
await queryInterface.createTable("Users", {
id: { type: Sequelize.INTEGER, primaryKey: true, autoIncrement: true },
ism: { type: Sequelize.STRING, allowNull: false },
email: { type: Sequelize.STRING, allowNull: false, unique: true },
parol: { type: Sequelize.STRING, allowNull: false },
rol: { type: Sequelize.ENUM("user", "admin"), defaultValue: "user" },
createdAt: { type: Sequelize.DATE, allowNull: false },
updatedAt: { type: Sequelize.DATE, allowNull: false },
});
// Indeks qo'shish (6.10: 2.3)
await queryInterface.addIndex("Users", ["email"]);
}
export async function down(queryInterface) {
await queryInterface.dropTable("Users"); // qaytarish (2.11)
}
// Ishlatish: npx sequelize-cli db:migrate (qo'llash); db:migrate:undo (bekor)Misol 8 — Migration: ustun qo'shish (2.11)
// Mavjud jadvalga ustun qo'shish (qo'lda ALTER emas — migration! — 2.11)
export async function up(queryInterface, Sequelize) {
await queryInterface.addColumn("Users", "telefon", {
type: Sequelize.STRING, allowNull: true,
});
}
export async function down(queryInterface) {
await queryInterface.removeColumn("Users", "telefon"); // qaytarish
}Misol 9 — Express controller (5.6, 5.10)
import { UserService } from "../services/userService.js";
export const userlarOl = async (req, res, next) => {
try {
const { rows, count } = await UserService.royxat(req.query); // findAndCountAll (Misol 4)
res.json({ success: true, data: rows, jami: count }); // (5.7)
} catch (err) { next(err); }
};
export const userYarat = async (req, res, next) => {
try {
const user = await UserService.yarat(req.body);
res.status(201).json({ success: true, data: user });
} catch (err) {
if (err.name === "SequelizeUniqueConstraintError") { // duplicate (2.16)
return res.status(409).json({ error: "Email band" }); // (5.10)
}
if (err.name === "SequelizeValidationError") { // validatsiya
return res.status(400).json({ error: err.errors.map(e => e.message) });
}
next(err);
}
};5. To'g'ri va noto'g'ri holatlar
1) N+1 (lazy loading tsiklda)
// N+1 (har user — alohida so'rov — 2.14)
const users = await User.findAll();
for (const u of users) await u.getOrders();
// eager (include — 1 so'rov)
const users = await User.findAll({ include: [Order] });2) Qo'lda schema o'zgartirish (migrationsiz)
DB'da qo'lda ALTER TABLE (muhitlar nomuvofiq — 2.11, 14)
migration fayl (git, up/down)3) Tranzaksiyada { transaction: t } unutish
// tranzaksiyadan tashqarida (atomik emas — 2.10)
await sequelize.transaction(async (t) => {
await User.update({...}); // t YO'Q!
});
// har amalga t
await User.update({...}, { transaction: t });4) Parolni qaytarish
// parol JSON'da (14, 2.16)
const user = await User.findByPk(id); // parol ham (scope yo'q bo'lsa)
// defaultScope exclude (Misol 2)5) Ortiqcha eager loading
// kerakmas include (sekin, murakkab — 2.14)
await User.findAll({ include: [Order, Profile, Settings, Logs] });
// faqat kerakli
await User.findAll({ include: [Order] });6. Keng tarqalgan xatolar va yechimlari
Xato 1 — SequelizeConnectionError
Sababi: DB ishlamayapti, URL/dialect noto'g'ri 2.3-bob. Yechimi: DB ishga tushiring; DATABASE_URL/dialect tekshiring; driver o'rnatilgan (pg/mysql2).
Xato 2 — SequelizeUniqueConstraintError
Sababi: unique buzildi (email — 2.4). Yechimi: 409 qaytaring (Misol 9); oldindan tekshiring.
Xato 3 — SequelizeValidationError
Sababi: model validatsiyasi buzildi (isEmail, len — 2.6). Yechimi: ma'lumotni to'g'irlang; 400 (Misol 9); API validatsiya 5.9-bob.
Xato 4 — N+1 (sekin)
Sababi: lazy loading tsiklda 2.14-bob. Yechimi: include (eager); logging: true bilan SQL ko'ring.
Xato 5 — association ... is not associated
Sababi: include'dagi model associate qilinmagan 2.8-bob. Yechimi: hasMany/belongsTo ta'riflang (Misol 3); as mosligini tekshiring.
Xato 6 — Migration ishlamaydi
Sababi: config noto'g'ri, yoki migration sintaksisi 2.11-bob. Yechimi: .sequelizerc/config tekshiring; up/down to'g'ri; db:migrate:status.
7. Integratsiya — bu mavzu stack'ning qayerida uchraydi
- SQL (6.4-6.10): ORM SQL ustida; SQL bilim shart.
- MySQL/PostgreSQL (6.5, 6.6): Sequelize dialect.
- Tranzaksiya/ACID 6.9-bob: sequelize.transaction.
- Indeks/N+1 6.10-bob: eager loading, migration indeks.
- Mongoose 6.2-bob: o'xshash ODM (NoSQL tomoni).
- Prisma/TypeORM (6.12, 6.13): muqobil ORM'lar.
- Auth 5.15-bob: User model, parol hash (hook).
- Express 5.6-bob: model controller'da.
- Migration/seed 6.16-bob: schema/ma'lumot boshqaruvi.
- Xavfsizlik (14): injection (parametrli), maxfiy maydon.
8. Eng yaxshi amaliyotlar (best practices)
- Migration har doim (qo'lda ALTER emas — git, up/down — 2.11, 14).
- Tranzaksiya ko'p yozuvda (managed —
{ transaction: t }har amalga — 2.10). - Eager loading o'ylab (N+1 oldini oling, ortiqcha emas — 2.9, 2.14).
- logging: true (dev) — generatsiya SQL'ni ko'ring (2.3, 2.14).
- Validatsiya (model) + hook (parol hash — 2.6); API validatsiya ham 5.9-bob.
- Maxfiy maydon scope'da yashiring (parol — defaultScope — 2.16).
- Raw query parametrli (replacements — murakkab so'rov — 2.15, 14).
- Xatolarni nom bo'yicha boshqaring (UniqueConstraint 409 — Misol 9, 5.10).
- Indeks model/migration'da 6.10-bob; findAndCountAll (sahifalash — Misol 4).
- SQL bilimini saqlang (ORM yashiradi, lekin kerak — 2.2).
9. Amaliy loyiha: "Sequelize bilan To'liq Backend"
Sequelize'ni professional darajada mustahkamlash.
Maqsad
Sequelize bilan to'liq, migration-asosli backend qurish: modellar, bog'lanishlar, tranzaksiya, eager loading va migration/seeding.
Talablar (requirements)
- Ulanish: Sequelize + pool; logging (dev); tekshiruv (Misol 1, 2.3).
- Modellar: User/Order/Product — validatsiya, hook (parol hash), defaultScope (Misol 2, 2.4, 2.6).
- Bog'lanishlar: one-to-many (User-Order), many-to-many (Order-Product — Misol 3, 2.8).
- CRUD service: Op operatorlar, findAndCountAll (sahifalash), qidiruv (Misol 4, 2.7).
- Eager loading: buyurtma+user+mahsulot; shartli include (Misol 5, 2.9).
- Tranzaksiya: buyurtma + zaxira (managed + lock — Misol 6, 2.10).
- Migration: jadval yaratish + ustun qo'shish (up/down — Misol 7, 8, 2.11).
- Seeding: boshlang'ich admin/kategoriya 2.12-bob.
- Express controller: xato boshqaruvi (UniqueConstraint409 — Misol 9).
- N+1 oldini olish: include bilan; logging bilan tekshiring 2.14-bob.
Maslahatlar (hint)
- Bog'lanish: hasMany + belongsTo birga (2.8, 5-xato).
- Eager:
include(N+1 — 2.9, 2.14). - Tranzaksiya: managed +
{ transaction: t }har amalga (2.10, 3-xato). - Migration: sequelize-cli, up/down (2.11, 2-xato).
- Parol: hook hash + defaultScope exclude (2.6, 2.16).
- logging: true — SQL ko'ring 2.14-bob.
"Tayyor" mezonlari (acceptance criteria)
- Sequelize ulanadi (pool, logging).
- Modellar (validatsiya, hook, scope).
- Bog'lanishlar (one-to-many, many-to-many).
- CRUD (operatorlar, sahifalash, qidiruv).
- Eager loading (include) ishlaydi.
- Tranzaksiya (managed + lock).
- Migration (yaratish + o'zgartirish).
- Seeding (boshlang'ich ma'lumot).
- Xato boshqaruvi (409/400).
- N+1 yo'q (include bilan).
Yechim kodi ataylab berilmagan — bu loyihani o'zingiz yozib ko'ring.
10. Xulosa va keyingi bobga ko'prik
Bu bobda birinchi ORM — Sequelize ni chuqur o'rgandik:
- ORM (jadvalobyekt — 2.1); afzallik/kamchilik (yashirin SQL — 2.2); ORM SQL'ni almashtirmaydi (SQL bilim shart).
- Model (define, DataTypes, validatsiya, hook — 2.4, 2.6); CRUD (findByPk/findAll/create — 2.5); Op operatorlar 2.7-bob.
- Associations (hasMany/belongsTo/belongsToMany — 2.8); eager loading (include — JOIN — 2.9); tranzaksiya (managed — 2.10).
- Migration (schema nazorat — up/down — 2.11) va seeding (boshlang'ich ma'lumot — 2.12); N+1 tuzog'i 2.14-bob; raw query 2.15-bob.
Keyingi bob — 6.12-bob: ORM — Prisma (schema, migrate, client, relations). Sequelize (klassik ORM) ni bildik; endi zamonaviy, type-safe ORM — Prisma ga o'tamiz. Prisma — boshqacha yondashuv: deklarativ schema fayli (schema.prisma), avtomatik generatsiya qilingan type-safe client, va ajoyib developer experience. TypeScript bilan eng yaxshi ORM hisoblanadi.
Foydalanilgan rasmiy/ishonchli manbalar
- sequelize.org — Model definition, Associations, Transactions, Migrations, Validations
- OneUptime — Sequelize ORM with Node.js 2026; sequelize.org/docs — eager loading, Op
- sequelize-cli — migrations, seeders
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!