Sequelize is an ORM (Object Relational Mapper).
A virtual field is a field that does NOT exist in the database.
fullName: {
type: DataTypes.VIRTUAL,
get() {
return `${this.firstName} ${this.lastName}`;
},
}
firstName → stored in DBlastName → stored in DBfullName → computed on the flyPostgreSQL requires DB to exist before using it.
psql -U postgre
CREATE DATABASE db_name;
| Option | Purpose |
|---|---|
paranoid: true |
Soft deletes — rows are not removed, deletedAt column is set |
underscored: true |
Convert camelCase → snake_case in DB (firstName → first_name) |
const { DataTypes } = require("sequelize");
const { sequelize } = require("../config/db");
const User = sequelize.define(
"User",
{
id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
email: {
type: DataTypes.STRING,
allowNull: false,
unique: true,
validate: {
isEmail: true,
},
},
firstName: {
type: DataTypes.STRING,
allowNull: false,
},
lastName: {
type: DataTypes.STRING,
allowNull: false,
},
role: {
type: DataTypes.ENUM("user", "admin", "moderator"),
defaultValue: "user",
},
fullName: {
type: DataTypes.VIRTUAL,
get() {
return `${this.firstName} ${this.lastName}`;
},
},
},
{
tableName: "users", // Custom table name
timestamps: true, // createdAt, updatedAt
paranoid: true, // Soft deletes (deletedAt)
underscored: true, // snake_case columns
},
);
const { DataTypes } = require('sequelize');
const Product = sequelize.define('Product', {
// String types
name: DataTypes.STRING, // VARCHAR(255)
description: DataTypes.TEXT, // TEXT
sku: DataTypes.STRING(50), // VARCHAR(50)
// Number types
price: DataTypes.DECIMAL(10, 2), // DECIMAL
quantity: DataTypes.INTEGER, // INTEGER
rating: DataTypes.FLOAT, // FLOAT
// Boolean
isActive: DataTypes.BOOLEAN,
// Date/Time
releaseDate: DataTypes.DATE, // DATETIME
time: DataTypes.TIME,
dateOnly: DataTypes.DATEONLY,
// JSON
metadata: DataTypes.JSON,
// Arrays (PostgreSQL only)
tags: DataTypes.ARRAY(DataTypes.STRING),
// Enum
status: DataTypes.ENUM('draft', 'published', 'archived'),
// UUID
uuid: {
type: DataTypes.UUID,
defaultValue: DataTypes.UUIDV4,
},
});
// Instance method
User.prototype.checkPassword = async function (password) {
return bcrypt.compare(password, this.password);
};
// Class method
User.findByEmail = async function (email) {
return this.findOne({ where: { email } });
};
//Hooks
User.beforeCreate(async (user) => {
user.password = await bcrypt.hash(user.password, 10);
});
//Usage
const user = await User.findByEmail("demo@example.com");
const isValid = await user.checkPassword("secret");
// Create single record
const user = await User.create({
email: 'john@example.com',
name: 'John Doe',
});
// Bulk create
const users = await User.bulkCreate([
{ email: 'user1@example.com', name: 'User 1' },
{ email: 'user2@example.com', name: 'User 2' },
]);
// Create with specific fields only
const user = await User.create(
{ email: 'jane@example.com', name: 'Jane', role: 'admin' },
{ fields: ['email', 'name'] } // Ignore 'role'
);