npx skills add https://github.com/mindrally/skills --skill sequelize你是一位精通 Sequelize ORM、Node.js 和数据库设计的专家,专注于模型关联、迁移和数据完整性。
import { Sequelize } from "sequelize";
// 选项 1:连接 URI
const sequelize = new Sequelize(process.env.DATABASE_URL!, {
dialect: "postgres",
logging: process.env.NODE_ENV === "development" ? console.log : false,
pool: {
max: 10,
min: 0,
acquire: 30000,
idle: 10000,
},
});
// 选项 2:单独参数
const sequelize = new Sequelize({
dialect: "postgres",
host: process.env.DB_HOST,
port: parseInt(process.env.DB_PORT || "5432"),
username: process.env.DB_USERNAME,
password: process.env.DB_PASSWORD,
database: process.env.DB_NAME,
logging: false,
});
// 测试连接
async function testConnection() {
try {
await sequelize.authenticate();
console.log("Connection established successfully.");
} catch (error) {
console.error("Unable to connect to the database:", error);
}
}
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
import {
Model,
DataTypes,
InferAttributes,
InferCreationAttributes,
CreationOptional,
} from "sequelize";
import { sequelize } from "./database";
class User extends Model<InferAttributes<User>, InferCreationAttributes<User>> {
declare id: CreationOptional<number>;
declare email: string;
declare name: string | null;
declare isActive: CreationOptional<boolean>;
declare createdAt: CreationOptional<Date>;
declare updatedAt: CreationOptional<Date>;
}
User.init(
{
id: {
type: DataTypes.INTEGER,
autoIncrement: true,
primaryKey: true,
},
email: {
type: DataTypes.STRING(255),
allowNull: false,
unique: true,
validate: {
isEmail: true,
},
},
name: {
type: DataTypes.STRING(255),
allowNull: true,
},
isActive: {
type: DataTypes.BOOLEAN,
defaultValue: true,
},
createdAt: DataTypes.DATE,
updatedAt: DataTypes.DATE,
},
{
sequelize,
tableName: "users",
modelName: "User",
underscored: true, // 列名使用蛇形命名法
}
);
export { User };
// 字符串类型
DataTypes.STRING(255) // VARCHAR(255)
DataTypes.TEXT // TEXT
DataTypes.TEXT("tiny") // TINYTEXT (MySQL)
// 数值类型
DataTypes.INTEGER // INTEGER
DataTypes.BIGINT // BIGINT
DataTypes.FLOAT // FLOAT
DataTypes.DOUBLE // DOUBLE
DataTypes.DECIMAL(10, 2) // DECIMAL(10,2)
// 布尔值
DataTypes.BOOLEAN // BOOLEAN / TINYINT(1)
// 日期/时间
DataTypes.DATE // DATETIME/TIMESTAMP
DataTypes.DATEONLY // DATE
DataTypes.TIME // TIME
// 二进制
DataTypes.BLOB // BLOB
// JSON
DataTypes.JSON // JSON (如果支持)
DataTypes.JSONB // JSONB (PostgreSQL)
// UUID
DataTypes.UUID // UUID
DataTypes.UUIDV4 // 自动生成 UUID v4
// 枚举
DataTypes.ENUM("active", "inactive", "pending")
// 数组 (仅限 PostgreSQL)
DataTypes.ARRAY(DataTypes.STRING)
class User extends Model {
declare id: number;
declare profile?: Profile;
}
class Profile extends Model {
declare id: number;
declare userId: number;
declare bio: string;
declare user?: User;
}
// 定义关联
User.hasOne(Profile, {
foreignKey: "userId",
as: "profile",
});
Profile.belongsTo(User, {
foreignKey: "userId",
as: "user",
});
class User extends Model {
declare id: number;
declare posts?: Post[];
}
class Post extends Model {
declare id: number;
declare authorId: number;
declare title: string;
declare author?: User;
}
// 定义关联
User.hasMany(Post, {
foreignKey: "authorId",
as: "posts",
});
Post.belongsTo(User, {
foreignKey: "authorId",
as: "author",
});
class Post extends Model {
declare id: number;
declare tags?: Tag[];
}
class Tag extends Model {
declare id: number;
declare name: string;
declare posts?: Post[];
}
// 定义关联(使用联结表)
Post.belongsToMany(Tag, {
through: "PostTags",
foreignKey: "postId",
otherKey: "tagId",
as: "tags",
});
Tag.belongsToMany(Post, {
through: "PostTags",
foreignKey: "tagId",
otherKey: "postId",
as: "posts",
});
// 查找所有
const users = await User.findAll();
// 带条件查找
const activeUsers = await User.findAll({
where: {
isActive: true,
},
});
// 查找一个
const user = await User.findOne({
where: { email: "user@example.com" },
});
// 按主键查找
const user = await User.findByPk(1);
// 查找或创建
const [user, created] = await User.findOrCreate({
where: { email: "user@example.com" },
defaults: {
name: "New User",
},
});
import { Op } from "sequelize";
// 多个条件
const users = await User.findAll({
where: {
[Op.and]: [
{ isActive: true },
{ createdAt: { [Op.gte]: new Date("2024-01-01") } },
],
},
});
// OR 条件
const users = await User.findAll({
where: {
[Op.or]: [{ name: "John" }, { name: "Jane" }],
},
});
// LIKE
const users = await User.findAll({
where: {
email: { [Op.like]: "%@example.com" },
},
});
// IN
const users = await User.findAll({
where: {
id: { [Op.in]: [1, 2, 3] },
},
});
// 比较运算符
const users = await User.findAll({
where: {
id: { [Op.gt]: 10 }, // 大于
age: { [Op.gte]: 18 }, // 大于或等于
score: { [Op.lt]: 100 }, // 小于
rank: { [Op.lte]: 5 }, // 小于或等于
status: { [Op.ne]: "inactive" }, // 不等于
},
});
// 加载用户及其帖子
const user = await User.findOne({
where: { id: 1 },
include: [
{
model: Post,
as: "posts",
},
],
});
// 嵌套预加载
const user = await User.findOne({
where: { id: 1 },
include: [
{
model: Post,
as: "posts",
include: [
{
model: Tag,
as: "tags",
},
],
},
],
});
// 带条件的预加载
const users = await User.findAll({
include: [
{
model: Post,
as: "posts",
where: {
publishedAt: { [Op.ne]: null },
},
required: false, // LEFT JOIN (包含没有帖子的用户)
},
],
});
const page = 1;
const pageSize = 20;
const { count, rows: users } = await User.findAndCountAll({
where: { isActive: true },
order: [
["createdAt", "DESC"],
["name", "ASC"],
],
limit: pageSize,
offset: (page - 1) * pageSize,
});
const totalPages = Math.ceil(count / pageSize);
// 计数
const count = await User.count({
where: { isActive: true },
});
// 求和
const total = await Order.sum("amount", {
where: { status: "completed" },
});
// 最大值/最小值
const maxPrice = await Product.max("price");
const minPrice = await Product.min("price");
// 分组
const stats = await Order.findAll({
attributes: [
"status",
[sequelize.fn("COUNT", sequelize.col("id")), "count"],
[sequelize.fn("SUM", sequelize.col("amount")), "total"],
],
group: ["status"],
});
// 创建单个记录
const user = await User.create({
email: "user@example.com",
name: "John Doe",
});
// 批量创建
const users = await User.bulkCreate(
[
{ email: "user1@example.com", name: "User 1" },
{ email: "user2@example.com", name: "User 2" },
],
{
validate: true, // 对每条记录运行验证
}
);
// 创建关联记录
const user = await User.create(
{
email: "user@example.com",
name: "John",
profile: {
bio: "Hello world",
},
},
{
include: [{ model: Profile, as: "profile" }],
}
);
// 更新单个记录
const user = await User.findByPk(1);
if (user) {
user.name = "Jane Doe";
await user.save();
}
// 使用新数据更新
await user.update({
name: "Jane Doe",
isActive: false,
});
// 批量更新
await User.update(
{ isActive: false },
{
where: {
lastLoginAt: { [Op.lt]: new Date("2024-01-01") },
},
}
);
// 删除单个记录
const user = await User.findByPk(1);
if (user) {
await user.destroy();
}
// 批量删除
await User.destroy({
where: {
isActive: false,
},
});
// 软删除 (需要在模型选项中设置 paranoid: true)
await user.destroy(); // 设置 deletedAt 而不是删除
// 恢复软删除的记录
await user.restore();
// 托管事务(推荐)
const result = await sequelize.transaction(async (t) => {
const user = await User.create(
{
email: "user@example.com",
name: "User",
},
{ transaction: t }
);
const post = await Post.create(
{
title: "First Post",
authorId: user.id,
},
{ transaction: t }
);
return { user, post };
});
// 非托管事务
const t = await sequelize.transaction();
try {
const user = await User.create(
{ email: "user@example.com" },
{ transaction: t }
);
await Post.create(
{ title: "Post", authorId: user.id },
{ transaction: t }
);
await t.commit();
} catch (error) {
await t.rollback();
throw error;
}
User.init(
{
// ... 列定义
},
{
sequelize,
hooks: {
beforeValidate: (user) => {
// 规范化邮箱
if (user.email) {
user.email = user.email.toLowerCase().trim();
}
},
beforeCreate: async (user) => {
// 哈希密码
if (user.password) {
user.password = await bcrypt.hash(user.password, 10);
}
},
afterCreate: async (user) => {
// 发送欢迎邮件
await sendWelcomeEmail(user.email);
},
beforeDestroy: async (user) => {
// 清理相关数据
await Post.destroy({ where: { authorId: user.id } });
},
},
}
);
// 或者单独定义钩子
User.addHook("beforeSave", "hashPassword", async (user) => {
if (user.changed("password")) {
user.password = await bcrypt.hash(user.password, 10);
}
});
User.addHook("beforeCreate", async (user, options) => {
if (options.transaction) {
// 对相关操作使用相同的事务
await AuditLog.create(
{
action: "user_created",
userId: user.id,
},
{ transaction: options.transaction }
);
}
});
User.init(
{
email: {
type: DataTypes.STRING,
allowNull: false,
validate: {
isEmail: {
msg: "必须是有效的邮箱地址",
},
notEmpty: true,
},
},
age: {
type: DataTypes.INTEGER,
validate: {
min: {
args: [0],
msg: "年龄必须为非负数",
},
max: {
args: [150],
msg: "年龄必须符合实际",
},
},
},
username: {
type: DataTypes.STRING,
validate: {
len: {
args: [3, 30],
msg: "用户名长度必须在 3 到 30 个字符之间",
},
isAlphanumeric: {
msg: "用户名只能包含字母和数字",
},
// 自定义验证器
async isUnique(value: string) {
const existing = await User.findOne({
where: { username: value },
});
if (existing) {
throw new Error("用户名已被占用");
}
},
},
},
},
{ sequelize }
);
# 生成迁移
npx sequelize-cli migration:generate --name create-users
# 运行迁移
npx sequelize-cli db:migrate
# 撤销上一次迁移
npx sequelize-cli db:migrate:undo
# 撤销所有迁移
npx sequelize-cli db:migrate:undo:all
// migrations/20240101000000-create-users.js
module.exports = {
async up(queryInterface, Sequelize) {
await queryInterface.createTable("users", {
id: {
type: Sequelize.INTEGER,
autoIncrement: true,
primaryKey: true,
},
email: {
type: Sequelize.STRING(255),
allowNull: false,
unique: true,
},
name: {
type: Sequelize.STRING(255),
allowNull: true,
},
is_active: {
type: Sequelize.BOOLEAN,
defaultValue: true,
},
created_at: {
type: Sequelize.DATE,
allowNull: false,
defaultValue: Sequelize.literal("CURRENT_TIMESTAMP"),
},
updated_at: {
type: Sequelize.DATE,
allowNull: false,
defaultValue: Sequelize.literal("CURRENT_TIMESTAMP"),
},
});
await queryInterface.addIndex("users", ["email"]);
},
async down(queryInterface) {
await queryInterface.dropTable("users");
},
};
// 不好:N+1 查询
const users = await User.findAll();
for (const user of users) {
const posts = await user.getPosts(); // 每个用户执行一次查询
}
// 好:使用 include 的单一查询
const users = await User.findAll({
include: [{ model: Post, as: "posts" }],
});
// sequelize 配置
{
development: {
// ...
},
production: {
// ...
migrationStorageTableName: "sequelize_migrations",
seederStorageTableName: "sequelize_seeds",
}
}
// 好:使用别名以提高清晰度
User.hasMany(Post, { as: "posts", foreignKey: "authorId" });
// 使用别名查询
const user = await User.findOne({
include: [{ model: Post, as: "posts" }],
});
// 使用 bulkCreate 时始终进行验证
await User.bulkCreate(users, { validate: true });
// 将相关操作包装在事务中
await sequelize.transaction(async (t) => {
// 所有操作使用同一事务
const order = await Order.create({ ... }, { transaction: t });
await OrderItem.bulkCreate(items, { transaction: t });
await Inventory.decrement("quantity", { ... }, { transaction: t });
});
User.addScope("active", {
where: { isActive: true },
});
User.addScope("withPosts", {
include: [{ model: Post, as: "posts" }],
});
// 使用作用域
const activeUsers = await User.scope("active").findAll();
const usersWithPosts = await User.scope(["active", "withPosts"]).findAll();
每周安装量
161
代码仓库
GitHub 星标数
42
首次出现
2026年1月25日
安全审计
安装于
gemini-cli139
opencode139
codex135
github-copilot129
cursor123
amp123
You are an expert in Sequelize ORM, Node.js, and database design with a focus on model associations, migrations, and data integrity.
import { Sequelize } from "sequelize";
// Option 1: Connection URI
const sequelize = new Sequelize(process.env.DATABASE_URL!, {
dialect: "postgres",
logging: process.env.NODE_ENV === "development" ? console.log : false,
pool: {
max: 10,
min: 0,
acquire: 30000,
idle: 10000,
},
});
// Option 2: Individual parameters
const sequelize = new Sequelize({
dialect: "postgres",
host: process.env.DB_HOST,
port: parseInt(process.env.DB_PORT || "5432"),
username: process.env.DB_USERNAME,
password: process.env.DB_PASSWORD,
database: process.env.DB_NAME,
logging: false,
});
// Test connection
async function testConnection() {
try {
await sequelize.authenticate();
console.log("Connection established successfully.");
} catch (error) {
console.error("Unable to connect to the database:", error);
}
}
import {
Model,
DataTypes,
InferAttributes,
InferCreationAttributes,
CreationOptional,
} from "sequelize";
import { sequelize } from "./database";
class User extends Model<InferAttributes<User>, InferCreationAttributes<User>> {
declare id: CreationOptional<number>;
declare email: string;
declare name: string | null;
declare isActive: CreationOptional<boolean>;
declare createdAt: CreationOptional<Date>;
declare updatedAt: CreationOptional<Date>;
}
User.init(
{
id: {
type: DataTypes.INTEGER,
autoIncrement: true,
primaryKey: true,
},
email: {
type: DataTypes.STRING(255),
allowNull: false,
unique: true,
validate: {
isEmail: true,
},
},
name: {
type: DataTypes.STRING(255),
allowNull: true,
},
isActive: {
type: DataTypes.BOOLEAN,
defaultValue: true,
},
createdAt: DataTypes.DATE,
updatedAt: DataTypes.DATE,
},
{
sequelize,
tableName: "users",
modelName: "User",
underscored: true, // Use snake_case for column names
}
);
export { User };
// String types
DataTypes.STRING(255) // VARCHAR(255)
DataTypes.TEXT // TEXT
DataTypes.TEXT("tiny") // TINYTEXT (MySQL)
// Numeric types
DataTypes.INTEGER // INTEGER
DataTypes.BIGINT // BIGINT
DataTypes.FLOAT // FLOAT
DataTypes.DOUBLE // DOUBLE
DataTypes.DECIMAL(10, 2) // DECIMAL(10,2)
// Boolean
DataTypes.BOOLEAN // BOOLEAN / TINYINT(1)
// Date/Time
DataTypes.DATE // DATETIME/TIMESTAMP
DataTypes.DATEONLY // DATE
DataTypes.TIME // TIME
// Binary
DataTypes.BLOB // BLOB
// JSON
DataTypes.JSON // JSON (if supported)
DataTypes.JSONB // JSONB (PostgreSQL)
// UUID
DataTypes.UUID // UUID
DataTypes.UUIDV4 // Auto-generate UUID v4
// Enum
DataTypes.ENUM("active", "inactive", "pending")
// Array (PostgreSQL only)
DataTypes.ARRAY(DataTypes.STRING)
class User extends Model {
declare id: number;
declare profile?: Profile;
}
class Profile extends Model {
declare id: number;
declare userId: number;
declare bio: string;
declare user?: User;
}
// Define associations
User.hasOne(Profile, {
foreignKey: "userId",
as: "profile",
});
Profile.belongsTo(User, {
foreignKey: "userId",
as: "user",
});
class User extends Model {
declare id: number;
declare posts?: Post[];
}
class Post extends Model {
declare id: number;
declare authorId: number;
declare title: string;
declare author?: User;
}
// Define associations
User.hasMany(Post, {
foreignKey: "authorId",
as: "posts",
});
Post.belongsTo(User, {
foreignKey: "authorId",
as: "author",
});
class Post extends Model {
declare id: number;
declare tags?: Tag[];
}
class Tag extends Model {
declare id: number;
declare name: string;
declare posts?: Post[];
}
// Define associations with junction table
Post.belongsToMany(Tag, {
through: "PostTags",
foreignKey: "postId",
otherKey: "tagId",
as: "tags",
});
Tag.belongsToMany(Post, {
through: "PostTags",
foreignKey: "tagId",
otherKey: "postId",
as: "posts",
});
// Find all
const users = await User.findAll();
// Find with conditions
const activeUsers = await User.findAll({
where: {
isActive: true,
},
});
// Find one
const user = await User.findOne({
where: { email: "user@example.com" },
});
// Find by primary key
const user = await User.findByPk(1);
// Find or create
const [user, created] = await User.findOrCreate({
where: { email: "user@example.com" },
defaults: {
name: "New User",
},
});
import { Op } from "sequelize";
// Multiple conditions
const users = await User.findAll({
where: {
[Op.and]: [
{ isActive: true },
{ createdAt: { [Op.gte]: new Date("2024-01-01") } },
],
},
});
// OR condition
const users = await User.findAll({
where: {
[Op.or]: [{ name: "John" }, { name: "Jane" }],
},
});
// LIKE
const users = await User.findAll({
where: {
email: { [Op.like]: "%@example.com" },
},
});
// IN
const users = await User.findAll({
where: {
id: { [Op.in]: [1, 2, 3] },
},
});
// Comparison operators
const users = await User.findAll({
where: {
id: { [Op.gt]: 10 }, // Greater than
age: { [Op.gte]: 18 }, // Greater than or equal
score: { [Op.lt]: 100 }, // Less than
rank: { [Op.lte]: 5 }, // Less than or equal
status: { [Op.ne]: "inactive" }, // Not equal
},
});
// Load user with posts
const user = await User.findOne({
where: { id: 1 },
include: [
{
model: Post,
as: "posts",
},
],
});
// Nested includes
const user = await User.findOne({
where: { id: 1 },
include: [
{
model: Post,
as: "posts",
include: [
{
model: Tag,
as: "tags",
},
],
},
],
});
// Include with conditions
const users = await User.findAll({
include: [
{
model: Post,
as: "posts",
where: {
publishedAt: { [Op.ne]: null },
},
required: false, // LEFT JOIN (include users without posts)
},
],
});
const page = 1;
const pageSize = 20;
const { count, rows: users } = await User.findAndCountAll({
where: { isActive: true },
order: [
["createdAt", "DESC"],
["name", "ASC"],
],
limit: pageSize,
offset: (page - 1) * pageSize,
});
const totalPages = Math.ceil(count / pageSize);
// Count
const count = await User.count({
where: { isActive: true },
});
// Sum
const total = await Order.sum("amount", {
where: { status: "completed" },
});
// Max/Min
const maxPrice = await Product.max("price");
const minPrice = await Product.min("price");
// Group by
const stats = await Order.findAll({
attributes: [
"status",
[sequelize.fn("COUNT", sequelize.col("id")), "count"],
[sequelize.fn("SUM", sequelize.col("amount")), "total"],
],
group: ["status"],
});
// Create single record
const user = await User.create({
email: "user@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" },
],
{
validate: true, // Run validations on each record
}
);
// Create with associations
const user = await User.create(
{
email: "user@example.com",
name: "John",
profile: {
bio: "Hello world",
},
},
{
include: [{ model: Profile, as: "profile" }],
}
);
// Update single record
const user = await User.findByPk(1);
if (user) {
user.name = "Jane Doe";
await user.save();
}
// Update with new data
await user.update({
name: "Jane Doe",
isActive: false,
});
// Bulk update
await User.update(
{ isActive: false },
{
where: {
lastLoginAt: { [Op.lt]: new Date("2024-01-01") },
},
}
);
// Delete single record
const user = await User.findByPk(1);
if (user) {
await user.destroy();
}
// Bulk delete
await User.destroy({
where: {
isActive: false,
},
});
// Soft delete (requires paranoid: true in model options)
await user.destroy(); // Sets deletedAt instead of deleting
// Restore soft-deleted record
await user.restore();
// Managed transaction (recommended)
const result = await sequelize.transaction(async (t) => {
const user = await User.create(
{
email: "user@example.com",
name: "User",
},
{ transaction: t }
);
const post = await Post.create(
{
title: "First Post",
authorId: user.id,
},
{ transaction: t }
);
return { user, post };
});
// Unmanaged transaction
const t = await sequelize.transaction();
try {
const user = await User.create(
{ email: "user@example.com" },
{ transaction: t }
);
await Post.create(
{ title: "Post", authorId: user.id },
{ transaction: t }
);
await t.commit();
} catch (error) {
await t.rollback();
throw error;
}
User.init(
{
// ... columns
},
{
sequelize,
hooks: {
beforeValidate: (user) => {
// Normalize email
if (user.email) {
user.email = user.email.toLowerCase().trim();
}
},
beforeCreate: async (user) => {
// Hash password
if (user.password) {
user.password = await bcrypt.hash(user.password, 10);
}
},
afterCreate: async (user) => {
// Send welcome email
await sendWelcomeEmail(user.email);
},
beforeDestroy: async (user) => {
// Clean up related data
await Post.destroy({ where: { authorId: user.id } });
},
},
}
);
// Or define hooks separately
User.addHook("beforeSave", "hashPassword", async (user) => {
if (user.changed("password")) {
user.password = await bcrypt.hash(user.password, 10);
}
});
User.addHook("beforeCreate", async (user, options) => {
if (options.transaction) {
// Use the same transaction for related operations
await AuditLog.create(
{
action: "user_created",
userId: user.id,
},
{ transaction: options.transaction }
);
}
});
User.init(
{
email: {
type: DataTypes.STRING,
allowNull: false,
validate: {
isEmail: {
msg: "Must be a valid email address",
},
notEmpty: true,
},
},
age: {
type: DataTypes.INTEGER,
validate: {
min: {
args: [0],
msg: "Age must be non-negative",
},
max: {
args: [150],
msg: "Age must be realistic",
},
},
},
username: {
type: DataTypes.STRING,
validate: {
len: {
args: [3, 30],
msg: "Username must be between 3 and 30 characters",
},
isAlphanumeric: {
msg: "Username must contain only letters and numbers",
},
// Custom validator
async isUnique(value: string) {
const existing = await User.findOne({
where: { username: value },
});
if (existing) {
throw new Error("Username already taken");
}
},
},
},
},
{ sequelize }
);
# Generate migration
npx sequelize-cli migration:generate --name create-users
# Run migrations
npx sequelize-cli db:migrate
# Undo last migration
npx sequelize-cli db:migrate:undo
# Undo all migrations
npx sequelize-cli db:migrate:undo:all
// migrations/20240101000000-create-users.js
module.exports = {
async up(queryInterface, Sequelize) {
await queryInterface.createTable("users", {
id: {
type: Sequelize.INTEGER,
autoIncrement: true,
primaryKey: true,
},
email: {
type: Sequelize.STRING(255),
allowNull: false,
unique: true,
},
name: {
type: Sequelize.STRING(255),
allowNull: true,
},
is_active: {
type: Sequelize.BOOLEAN,
defaultValue: true,
},
created_at: {
type: Sequelize.DATE,
allowNull: false,
defaultValue: Sequelize.literal("CURRENT_TIMESTAMP"),
},
updated_at: {
type: Sequelize.DATE,
allowNull: false,
defaultValue: Sequelize.literal("CURRENT_TIMESTAMP"),
},
});
await queryInterface.addIndex("users", ["email"]);
},
async down(queryInterface) {
await queryInterface.dropTable("users");
},
};
// Bad: N+1 queries
const users = await User.findAll();
for (const user of users) {
const posts = await user.getPosts(); // Query per user
}
// Good: Single query with include
const users = await User.findAll({
include: [{ model: Post, as: "posts" }],
});
// sequelize config
{
development: {
// ...
},
production: {
// ...
migrationStorageTableName: "sequelize_migrations",
seederStorageTableName: "sequelize_seeds",
}
}
// Good: Using aliases for clarity
User.hasMany(Post, { as: "posts", foreignKey: "authorId" });
// Query with alias
const user = await User.findOne({
include: [{ model: Post, as: "posts" }],
});
// Always validate when using bulkCreate
await User.bulkCreate(users, { validate: true });
// Wrap related operations in transactions
await sequelize.transaction(async (t) => {
// All operations use the same transaction
const order = await Order.create({ ... }, { transaction: t });
await OrderItem.bulkCreate(items, { transaction: t });
await Inventory.decrement("quantity", { ... }, { transaction: t });
});
User.addScope("active", {
where: { isActive: true },
});
User.addScope("withPosts", {
include: [{ model: Post, as: "posts" }],
});
// Use scopes
const activeUsers = await User.scope("active").findAll();
const usersWithPosts = await User.scope(["active", "withPosts"]).findAll();
Weekly Installs
161
Repository
GitHub Stars
42
First Seen
Jan 25, 2026
Security Audits
Gen Agent Trust HubPassSocketPassSnykPass
Installed on
gemini-cli139
opencode139
codex135
github-copilot129
cursor123
amp123
Tailwind CSS v4 + shadcn/ui 生产级技术栈配置指南与最佳实践
2,600 周安装