Skip to content

Sequelize 学习笔记

仲灏2021-12-24约 1 分钟

<div style="display: none;" hidden="true" aria-hidden="true" data-nosnippet>Are you an LLM? You can read better optimized documentation at /pages/9da7c4.md for this page in Markdown format</div>

Sequelize 中文文档入门

核心概念

基本设置

表名推断

默认情况下,当未提供表名时,Sequelize 会自动将模型名复数并将其用作表名. 这种复数是通过称为 inflection 的库在后台完成的,因此可以正确计算不规则的复数(例如 person -> people).

强制表名称等于模型名称

javascript
sequelize.define('User', {
  // ... (属性)
}, {
  freezeTableName: true
});

直接提供表名

javascript
sequelize.define('User', {
  // ... (属性)
}, {
  tableName: 'Employees'
});

模型同步

  • User.sync() - 如果表不存在,则创建该表(如果已经存在,则不执行任何操作)

  • User.sync({ force: true }) - 将创建表,如果表已经存在,则将其首先删除

  • User.sync({ alter: true }) - 这将检查数据库中表的当前状态(它具有哪些列,它们的数据类型等),然后在表中进行必要的更改以使其与模型匹配

javascript
await User.sync({ force: true });
console.log("用户模型表刚刚(重新)创建!");

时间戳

默认情况下,Sequelize 使用数据类型 DataTypes.DATE 自动向每个模型添加 createdAtupdatedAt 字段. 这些字段会自动进行管理 - 每当你使用Sequelize 创建或更新内容时,这些字段都会被自动设置. createdAt 字段将包含代表创建时刻的时间戳,而 updatedAt 字段将包含最新更新的时间戳.

对于带有 timestamps: false 参数的模型,可以禁用此行为:

javascript
sequelize.define('User', {
// ... (属性)
}, {
  timestamps: false
});

也可以只启用 createdAt/updatedAt 之一,并为这些列提供自定义名称:

javascript
class Foo extends Model {}
Foo.init({ /* 属性 */ }, {
  sequelize,
// 不要忘记启用时间戳!
  timestamps: true,
// 不想要 createdAt
  createdAt: false,
// 想要 updatedAt 但是希望名称叫做 updateTimestamp
  updatedAt: 'updateTimestamp'
});

获取的值变更, 设置值变更(getter, setter)

获取的值变更

javascript
const User = sequelize.define('user', {
  // 假设我们想要以大写形式查看每个用户名,
  // 即使它们在数据库本身中不一定是大写的
  username: {
    type: DataTypes.STRING,
    get() {
      const rawValue = this.getDataValue(username);
      return rawValue ? rawValue.toUpperCase() : null;
    }
  }
});

设置值变更

javascript
const User = sequelize.define('user', {
  username: DataTypes.STRING,
  password: {
    type: DataTypes.STRING,
    set(value) {
      // 在数据库中以明文形式存储密码是很糟糕的.
      // 使用适当的哈希函数来加密哈希值更好.
      this.setDataValue('password', hash(value));
    }
  }
});

模型 Model

定义模型

javascript
class Foo extends Model {}
Foo.init({
  // 如果未设置,实例化将自动将标志设置为true
  flag: { type: DataTypes.BOOLEAN, allowNull: false, defaultValue: true },

  // 日期的默认值=>当前时间
  myDate: { type: DataTypes.DATE, defaultValue: DataTypes.NOW },

  // setting allowNull to false will add NOT NULL to the column, which means an error will be
  // thrown from the DB when the query is executed if the column is null. If you want to check that a value
  // is not null before querying the DB, look at the validations section below.
  title: { type: DataTypes.STRING, allowNull: false },

  // Creating two objects with the same value will throw an error. The unique property can be either a
  // boolean, or a string. If you provide the same string for multiple columns, they will form a
  // composite unique key.
  uniqueOne: { type: DataTypes.STRING,  unique: 'compositeIndex' },
  uniqueTwo: { type: DataTypes.INTEGER, unique: 'compositeIndex' },

  // The unique property is simply a shorthand to create a unique constraint.
  someUnique: { type: DataTypes.STRING, unique: true },

  // Go on reading for further information about primary keys
  identifier: { type: DataTypes.STRING, primaryKey: true },

  // autoIncrement can be used to create auto_incrementing integer columns
  incrementMe: { type: DataTypes.INTEGER, autoIncrement: true },

  // You can specify a custom column name via the 'field' attribute:
  fieldWithUnderscores: { type: DataTypes.STRING, field: 'field_with_underscores' },

  // It is possible to create foreign keys:
  bar_id: {
    type: DataTypes.INTEGER,

    references: {
      // This is a reference to another model
      model: Bar,

      // This is the column name of the referenced model
      key: 'id',

      // With PostgreSQL, it is optionally possible to declare when to check the foreign key constraint, passing the Deferrable type.
      deferrable: Deferrable.INITIALLY_IMMEDIATE
      // Options:
      // - `Deferrable.INITIALLY_IMMEDIATE` - Immediately check the foreign key constraints
      // - `Deferrable.INITIALLY_DEFERRED` - Defer all foreign key constraint check to the end of a transaction
      // - `Deferrable.NOT` - Don't defer the checks at all (default) - This won't allow you to dynamically change the rule in a transaction
    }
  },

  // Comments can only be added to columns in MySQL, MariaDB, PostgreSQL and MSSQL
  commentMe: {
    type: DataTypes.INTEGER,
    comment: 'This is a column name that has a comment'
  }
}, {
  sequelize,
  modelName: 'foo',

  // Using `unique: true` in an attribute above is exactly the same as creating the index in the model's options:
  indexes: [{ unique: true, fields: ['someUnique'] }]
});

验证和约束

使用自定义错误消息代替validator提供的错误消息。使用一个对象,而不是纯值或参数数组,例如验证器不需要参数,可以给自定义消息

javascript
isInt: {
  msg: "必须是整数"
}

你也可以有条件地允许空值,用一个定制的验证器,因为它不会被跳过:

javascript
class User extends Model {}
User.init({
  age: Sequelize.INTEGER,
  name: {
    type: DataTypes.STRING,
    allowNull: true,
    validate: {
      customValidator(value) {
        if (value === null && this.age !== 10) {
          throw new Error("name can't be null unless age is 10");
        }
      })
    }
  }
}, { sequelize });

基本查询

排序

order选项接受一个项目数组来对查询进行排序,或者使用sequelize方法。这些项目本身就是以[列,方向]的形式排列的。该列将被正确转义,方向将在有效方向的白名单中被检查(如ASC、DESC、NULLS FIRST等)。

plain
Subtask.findAll({
  order: [
    // 将转义标题和验证DESC对一个有效的方向参数的列表
    ['title', 'DESC'],
    // 按最大(年龄)降序
    sequelize.fn('max', sequelize.col('age')),
    // 按最大(年龄)降序
    [sequelize.fn('max', sequelize.col('age')), 'DESC'],
    // 将顺序由其他函数(' col1 ', 12, 'lalala') 降序
    [sequelize.fn('otherfunction', sequelize.col('col1'), 12, 'lalala'), 'DESC'],
    // 将使用模型名称作为关联的名称来订购关联模型的createdAt。
    [Task, 'createdAt', 'DESC'],
    // 将使用模型名称作为关联的名称,通过关联模型的createdAt进行排序。
    [Task, Project, 'createdAt', 'DESC'],
    // 排序将由一个关联模型的创建使用名称的关联
    ['Task', 'createdAt', 'DESC'],
    // 使用关联的名称来创建嵌套的关联模型排序
    ['Task', 'Project', 'createdAt', 'DESC'],
    // 通过使用关联对象来创建关联模型排序. (首选方法)
    [Subtask.associations.Task, 'createdAt', 'DESC'],
    // 通过使用关联对象的嵌套关联模型的创建排序。 (首选方法)
    [Subtask.associations.Task, Task.associations.Project, 'createdAt', 'DESC'],
    // 通过使用一个简单的关联对象来创建一个关联模型。
    [{model: Task, as: 'Task'}, 'createdAt', 'DESC'],
    // 由嵌套关联模型的createdAt创建简单关联对象。
    [{model: Task, as: 'Task'}, {model: Project, as: 'Project'}, 'createdAt', 'DESC']
  ],
  // 最大年龄降序
  order: sequelize.literal('max(age) DESC'),
  // 当方向被省略时,按最大年龄升序假设升序是默认的顺序
  // 当方向被省略时,按年龄升序排列默认为升序
  order: sequelize.random()
});