Sequelize 模型

基于类的模型(TypeScript)

import { Model, DataTypes, Sequelize, Optional } from "sequelize";

interface UserAttributes {
  id: number;
  email: string;
  name: string | null;
  role: "admin" | "user";
  createdAt?: Date;
}

interface UserCreationAttributes extends Optional<UserAttributes, "id"> {}

class User extends Model<UserAttributes, UserCreationAttributes>
  implements UserAttributes {
  declare id: number;
  declare email: string;
  declare name: string | null;
  declare role: "admin" | "user";
  declare readonly createdAt: Date;
  declare readonly updatedAt: Date;

  static initialize(sequelize: Sequelize) {
    User.init(
      {
        id:    { type: DataTypes.INTEGER, autoIncrement: true, primaryKey: true },
        email: { type: DataTypes.STRING, allowNull: false, unique: true,
                 validate: { isEmail: true } },
        name:  { type: DataTypes.STRING, allowNull: true },
        role:  { type: DataTypes.ENUM("admin","user"), defaultValue: "user" }
      },
      {
        sequelize,
        tableName: "users",
        timestamps: true,
        paranoid: true,          // soft deletes (deletedAt column)
        underscored: true        // snake_case column names
      }
    );
  }
}

DataTypes 参考

DataTypeSQL 类型说明
STRING(n)VARCHAR(n)默认 255
TEXTTEXT无界字符串
INTEGERINT
BIGINTBIGINT返回字符串(JS 精度限制)
FLOATFLOAT
DECIMAL(p,s)DECIMAL(p,s)精确数值
BOOLEANBOOLEAN / TINYINT
DATEDATETIME / TIMESTAMP
DATEONLYDATE仅日期,不含时间
JSON / JSONBJSON / JSONBPostgreSQL 使用 JSONB
ENUM(...vals)ENUM
ARRAY(type)ARRAY仅 PostgreSQL
UUIDUUID / CHAR(36)
VIRTUAL计算字段,不存储

钩子

import * as bcrypt from "bcrypt";

User.addHook("beforeCreate", async (user) => {
  if (user.password) {
    user.password = await bcrypt.hash(user.password, 12);
  }
});

User.addHook("afterCreate", async (user, options) => {
  await AuditLog.create({ action: "user_created", userId: user.id });
});

// Inline hooks in init()
User.init({ ... }, {
  sequelize,
  hooks: {
    beforeUpdate: async (user) => {
      if (user.changed("email")) {
        user.emailVerified = false;
      }
    }
  }
});

// Available hooks:
// beforeValidate, afterValidate
// beforeCreate,  afterCreate
// beforeUpdate,  afterUpdate
// beforeSave,    afterSave
// beforeDestroy, afterDestroy
// beforeBulkCreate, afterBulkCreate

作用域

User.init({ ... }, {
  sequelize,
  defaultScope: {
    where:      { isActive: true },
    attributes: { exclude: ["password"] }
  },
  scopes: {
    withPassword: { attributes: { include: ["password"] } },
    admins:       { where: { role: "admin" } },
    recent:       { order: [["createdAt", "DESC"]], limit: 10 },
    withPosts: {
      include: [{ model: Post, as: "posts" }]
    }
  }
});

// Using scopes
User.scope("admins").findAll();
User.scope(["admins", "recent"]).findAll();
User.scope("withPassword").findOne({ where: { email: "[email protected]" } });
User.unscoped().findAll();  // ignore defaultScope

查询

const { Op } = require("sequelize");

// findAll with operators
await User.findAll({
  where: {
    age:   { [Op.between]: [18, 65] },
    email: { [Op.like]: "%@example.com" },
    role:  { [Op.in]: ["admin", "user"] },
    [Op.or]: [
      { firstName: "Alice" },
      { lastName:  "Smith" }
    ]
  },
  order:      [["createdAt", "DESC"]],
  limit:      20,
  offset:     0,
  attributes: ["id", "email", "name"]
});

// findOrCreate
const [user, created] = await User.findOrCreate({
  where:    { email: "[email protected]" },
  defaults: { name: "Alice", role: "user" }
});

// upsert
await User.upsert({ email: "[email protected]", name: "Alice" });