可以在此处访问此博客的代码
可以在此处访问此博客的代码
可以在此处访问此博客的 Markdown
Sequelize 是最著名的 Node ORM,功能相当丰富,但在使用它的时候,我花了很多时间在文档和各种谷歌搜索之间徘徊。
 这份 Cheatsheet 正是我一直想要的,但却一直找不到。
 发现任何错误或缺失的内容?请在下方评论,或者更好的是,向文末链接的仓库发送拉取请求。
npm install --save sequelize
您还需要安装您正在使用的数据库的驱动程序。
# One of the following:
npm install --save pg pg-hstore # Postgres If node version < 14 use pg@7.12.1 instead
npm install --save mysql2
npm install --save mariadb
npm install --save sqlite3
npm install --save tedious # Microsoft SQL Server
必须创建一个 Sequelize 实例才能连接到数据库。默认情况下,此连接保持打开并用于所有查询,但可以显式关闭。
const Sequelize = require('sequelize');
// Option 1: Passing parameters separately
const sequelize = new Sequelize('database', 'username', 'password', {
  host: 'localhost',
  dialect: /* one of 'mysql' | 'mariadb' | 'postgres' | 'mssql' */
});
// Option 2: Passing a connection URI
const sequelize = new Sequelize('postgres://user:pass@example.com:5432/dbname');
// For SQLite, use this instead
const sequelize = new Sequelize({
  dialect: 'sqlite',
  storage: 'path/to/database.sqlite'
});
有关连接不同方言的更多详细信息,请查看官方文档
.authenticate()可以与创建的实例一起使用来检查连接是否正常工作。
sequelize
  .authenticate()
  .then(() => {
    console.log("Connection has been established successfully.");
  })
  .catch((err) => {
    console.error("Unable to connect to the database:", err);
  });
sequelize.close();
要定义模型和表之间的映射,我们可以使用该.define()方法
 设置仅具有属性及其数据类型的基本模型
const ModelName = sequelize.define("tablename", {
  // s will be appended automatically to the tablename
  firstColumn: Sequelize.INTEGER,
  secondColumn: Sequelize.STRING,
});
要获取 Sequelize 支持的所有数据类型的列表,请查看官方文档
除了数据类型之外,还可以在每列上设置许多其他选项
const ModelName = sequelize.define("tablename", {
  firstColumn: {
    // REQUIRED
    type: Sequelize.INTEGER,
    // OPTIONAL
    allowNull: false, // true by default
    defaultValue: 1,
    primaryKey: true, // false by default
    autoIncrement: true, // false by default
    unique: true,
    field: "first_column", // To change the field name in actual table
  },
});
要创建复合唯一键,请为要包含在复合唯一键中的所有列中的约束赋予相同的名称
const ModelName = sequelize.define("tablename", {
  firstColumn: {
    type: Sequelize.INTEGER,
    unique: "compositeIndex",
  },
  secondColumn: {
    type: Sequelize.INTEGER,
    unique: "compositeIndex",
  },
});
也可以使用索引创建它们
const ModelName = sequelize.define(
  "tablename",
  {
    firstColumn: Sequelize.INTEGER,
    secondColumn: Sequelize.INTEGER,
  },
  {
    indexes: [
      {
        unique: true,
        fields: ["firstColumn", "secondColumn"],
      },
    ],
  }
);
Getter 可用于在经过某些处理后获取列的值。Setter
 可用于在将值保存到表中之前对其进行处理。
const Employee = sequelize.define("employee", {
  name: {
    type: Sequelize.STRING,
    allowNull: false,
    get() {
      const title = this.getDataValue("title");
      // 'this' allows you to access attributes of the instance
      return this.getDataValue("name") + " (" + title + ")";
    },
  },
  title: {
    type: Sequelize.STRING,
    allowNull: false,
    set(val) {
      this.setDataValue("title", val.toUpperCase());
    },
  },
});
Employee.create({ name: "John Doe", title: "senior engineer" }).then(
  (employee) => {
    console.log(employee.get("name")); // John Doe (SENIOR ENGINEER)
    console.log(employee.get("title")); // SENIOR ENGINEER
  }
);
有关 Getters 和 Setters 的更多详细信息,请查看官方文档
验证自动运行于create,update并且save
const ModelName = sequelize.define("tablename", {
  firstColumn: {
    type: Sequelize.STRING,
    validate: {
      is: ["^[a-z]+$", "i"], // will only allow letters
      is: /^[a-z]+$/i, // same as the previous example using real RegExp
      not: ["[a-z]", "i"], // will not allow letters
      isEmail: true, // checks for email format (foo@bar.com)
      isUrl: true, // checks for url format (http://foo.com)
      isIP: true, // checks for IPv4 (129.89.23.1) or IPv6 format
      isIPv4: true, // checks for IPv4 (129.89.23.1)
      isIPv6: true, // checks for IPv6 format
      isAlpha: true, // will only allow letters
      isAlphanumeric: true, // will only allow alphanumeric characters, so "_abc" will fail
      isNumeric: true, // will only allow numbers
      isInt: true, // checks for valid integers
      isFloat: true, // checks for valid floating point numbers
      isDecimal: true, // checks for any numbers
      isLowercase: true, // checks for lowercase
      isUppercase: true, // checks for uppercase
      notNull: true, // won't allow null
      isNull: true, // only allows null
      notEmpty: true, // don't allow empty strings
      equals: "specific value", // only allow a specific value
      contains: "foo", // force specific substrings
      notIn: [["foo", "bar"]], // check the value is not one of these
      isIn: [["foo", "bar"]], // check the value is one of these
      notContains: "bar", // don't allow specific substrings
      len: [2, 10], // only allow values with length between 2 and 10
      isUUID: 4, // only allow uuids
      isDate: true, // only allow date strings
      isAfter: "2011-11-05", // only allow date strings after a specific date
      isBefore: "2011-11-05", // only allow date strings before a specific date
      max: 23, // only allow values <= 23
      min: 23, // only allow values >= 23
      isCreditCard: true, // check for valid credit card numbers
      // Examples of custom validators:
      isEven(value) {
        if (parseInt(value) % 2 !== 0) {
          throw new Error("Only even values are allowed!");
        }
      },
    },
  },
});
const ModelName = sequelize.define(
  "tablename",
  {
    firstColumn: Sequelize.INTEGER,
    secondColumn: Sequelize.INTEGER,
  },
  {
    validate: {
      // Define your Model Wide Validations here
      checkSum() {
        if (this.firstColumn + this.secondColumn < 10) {
          throw new Error("Require sum of columns >=10");
        }
      },
    },
  }
);
const ModelName = sequelize.define(
  "tablename",
  {
    firstColumn: Sequelize.INTEGER,
  },
  {
    timestamps: true, // Enable timestamps
    createdAt: false, // Don't create createdAt
    updatedAt: false, // Don't create updatedAt
    updatedAt: "updateTimestamp", // updatedAt should be called updateTimestamp
  }
);
Sequelize 可以自动创建模型中定义的表、关系和约束
ModelName.sync(); // Create the table if not already present
// Force the creation
ModelName.sync({ force: true }); // this will drop the table first and re-create it afterwards
ModelName.drop(); // drop the tables
您可以使用 sequelize 一次管理所有模型
sequelize.sync(); // Sync all models that aren't already in the database
sequelize.sync({ force: true }); // Force sync all models
sequelize.sync({ force: true, match: /_test$/ }); // Run .sync() only if database name ends with '_test'
sequelize.drop(); // Drop all tables
Sequelize 模型是 ES6 类。我们可以轻松添加自定义实例或类级别的方法。
const ModelName = sequelize.define("tablename", {
  firstColumn: Sequelize.STRING,
  secondColumn: Sequelize.STRING,
});
// Adding a class level method
ModelName.classLevelMethod = function () {
  return "This is a Class level method";
};
// Adding a instance level method
ModelName.prototype.instanceLevelMethod = function () {
  return [this.firstColumn, this.secondColumn].join(" ");
};
const User = sequelize.define(
  "User",
  {
    /* attributes */
  },
  {
    indexes: [
      // Create a unique index on email
      {
        unique: true,
        fields: ["email"],
      },
      // Creates a gin index on data with the jsonb_path_ops operator
      {
        fields: ["data"],
        using: "gin",
        operator: "jsonb_path_ops",
      },
      // By default index name will be [table]_[fields]
      // Creates a multi column partial index
      {
        name: "public_by_author",
        fields: ["author", "status"],
        where: {
          status: "public",
        },
      },
      // A BTREE index with an ordered field
      {
        name: "title_index",
        using: "BTREE",
        fields: [
          "author",
          {
            attribute: "title",
            collate: "en_US",
            order: "DESC",
            length: 5,
          },
        ],
      },
    ],
  }
);
定义有四种类型。它们成对使用。
 例如,我们定义两个模型
const Foo = sequelize.define("foo" /* ... */);
const Bar = sequelize.define("bar" /* ... */);
我们将要调用其函数的模型称为源模型,作为参数传递的模型称为目标模型。
Foo.hasOne(Bar, {
  /* options */
});
这说明 Foo 和 Bar 之间存在一对一关系,外键定义在 Bar 中
Foo.belongsTo(Bar, {
  /* options */
});
这说明 Foo 和 Bar 之间存在一对一或一对多关系,且外键定义在 Foo 中
Foo.hasMany(Bar, {
  /* options */
});
这说明 Foo 和 Bar 之间存在一对多关系,外键定义在 Bar 中
Foo.belongsToMany(Bar, {
  // REQUIRED
  through: "C", // Model can also be passed here
  /* options */
});
这表明 Foo 和 Bar 之间存在多对多关系,通过连接表 C
要建立一对一关系,我们只需编写
Foo.hasOne(Bar);
Bar.belongsTo(Foo);
在上述情况下,未传递任何选项。这将自动在 Bar 中创建一个外键列,引用 Foo 的主键。如果 Foo 的主键列名为 email,则在 Bar 中生成的列将为 fooEmail。
可以传递以下选项来定制关系。
Foo.hasOne(Bar, {
  foreignKey: "customNameForFKColumn", // Name for new column added to Bar
  sourceKey: "email", // Column in Foo that FK will reference to
  // The possible choices are RESTRICT, CASCADE, NO ACTION, SET DEFAULT and SET NULL
  onDelete: "RESTRICT", // Default is SET NULL
  onUpdate: "RESTRICT", // Default is CASCADE
});
Bar.belongsTo(Foo, {
  foreignKey: "customNameForFKColumn", // Name for new column added to Bar
});
要建立一对一关系,我们只需编写
Foo.hasMany(Bar);
Bar.belongsTo(Foo);
在上述情况下,未传递任何选项。这将自动在 Bar 中创建一个外键列,引用 Foo 的主键。如果 Foo 的主键列名为 email,则在 Bar 中生成的列将为 fooEmail。
可以传递以下选项来定制关系。
Foo.hasMany(Bar, {
  foreignKey: "customNameForFKColumn", // Name for new column added to Bar
  sourceKey: "email", // Column in Foo that FK will reference to
  // The possible choices are RESTRICT, CASCADE, NO ACTION, SET DEFAULT and SET NULL
  onDelete: "RESTRICT", // Default is SET NULL
  onUpdate: "RESTRICT", // Default is CASCADE
});
Bar.belongsTo(Foo, {
  foreignKey: "customNameForFKColumn", // Name for new column added to Bar
});
要建立多对多关系,我们只需编写
// This will create a new table rel referencing the PK(by default) of both the tables
Foo.belongsToMany(Bar, { through: "rel" });
Bar.belongsToMany(Foo, { through: "rel" });
可以传递以下选项来定制关系。
Foo.belongsToMany(Bar, {
  as: "Bar",
  through: "rel",
  foreignKey: "customNameForFoo", // Custom name for column in rel referencing to Foo
  sourceKey: "name", // Column in Foo which rel will reference to
});
Bar.belongsToMany(Foo, {
  as: "Foo",
  through: "rel",
  foreignKey: "customNameForBar", // Custom name for column in rel referencing to Bar
  sourceKey: "name", // Column in Foo which rel will reference to
});
创建实例有两种方式
我们可以使用 build 方法创建非持久化(不保存到表中)实例。它们将自动获取定义模型时指定的默认值。
 要保存到表中,我们需要显式地保存这些实例。
const instance = ModelName.build({
  firstColumn: "Lorem Ipsum",
  secondColumn: "Dotor",
});
// To save this instance to the db
instance.save().then((savedInstance) => {});
我们可以创建一个方法来创建持久(保存到表中)实例
const instance = ModelName.create({
  firstColumn: "Lorem Ipsum",
  secondColumn: "Dotor",
});
有两种方法可以更新任何实例
// Way 1
instance.secondColumn = "Updated Dotor";
instance.save().then(() => {});
// To update only some of the modified fields
instance.save({ fields: ["secondColumn"] }).then(() => {});
// Way 2
instance
  .update({
    secondColumn: "Updated Dotor",
  })
  .then(() => {});
// To update only some of the modified fields
instance
  .update(
    {
      secondColumn: "Updated Dotor",
    },
    { fields: ["secondColumn"] }
  )
  .then(() => {});
删除/销毁任何实例
instance.destroy().then(() => {});
返回具有给定主键值的行。
ModelName.findByPK(PKvalue).then((foundResult) => {});
返回符合给定条件的第一行。
ModelName.findOne({
  // Optional options
  // Filtering results using where
  where: { firstColumn: "value" },
  // Returning only specified columns
  attributes: ["firstColumn", "secondColumn"],
}).then((foundResult) => {});
返回符合指定条件的行。如果不存在这样的行,则创建并返回该行。
ModelName.findOrCreate({
  // Conditions that must be met
  where: { firstColumn: "lorem ipsum" },
  // Value of other columns to be set if no such row found
  defaults: { secondColumn: "dotor" },
}).then(([result, created]) => {}); //Created is a bool which tells created or not
返回满足条件的所有行
ModelName.findAll({
  // Optional Options
  where: {
    firstColumn: "lorem ipsum",
  },
  offset: 10,
  limit: 2,
}).then((results) => {});
返回满足条件的所有行及其计数
ModelName.findAndCountAll({
  where: {
    firstColumn: "lorem ipsum",
  },
}).then((results) => {
  console.log(results.count);
  console.log(results.rows);
});
返回满足条件的行数
ModelName.count({
  where: {
    firstColumn: "lorem ipsum",
  },
}).then((c) => {});
返回具有给定条件的最大值的列的值
ModelName.max("age", {
  where: {
    firstColumn: "lorem ipsum",
  },
}).then((maxAge) => {});
返回具有给定条件的最小值的列的值
ModelName.min("age", {
  where: {
    firstColumn: "lorem ipsum",
  },
}).then((minAge) => {});
返回满足给定条件的列的所有值的总和
ModelName.sum({
  where: {
    firstColumn: "lorem ipsum",
  },
}).then((sumAge) => {});
哪里可以用来过滤我们处理的结果
我们可以直接传递值
ModelName.findAll({
  where: {
    firstColumn: "lorem ipsum",
  },
});
我们可以使用 AND 和 OR
const Op = Sequelize.Op;
ModelName.findAll({
  where: {
    [Op.and]: [{ secondColumn: 5 }, { thirdColumn: 6 }],
    [Op.or]: [{ secondColumn: 5 }, { secondColumn: 6 }],
  },
});
我们可以使用其他各种运算符
const Op = Sequelize.Op;
ModelName.findAll({
  where: {
    firstColumn: {
      [Op.ne]: "lorem ipsum dotor", // Not equal to
    },
  },
});
我们也可以混合搭配
const Op = Sequelize.Op;
ModelName.findAll({
  where: {
    [Op.or]: {
      [Op.lt]: 1000,
      [Op.eq]: null,
    },
  },
});
以下是运营商的完整列表
const Op = Sequelize.Op
[Op.and]: [{a: 5}, {b: 6}] // (a = 5) AND (b = 6)
[Op.or]: [{a: 5}, {a: 6}]  // (a = 5 OR a = 6)
[Op.gt]: 6,                // > 6
[Op.gte]: 6,               // >= 6
[Op.lt]: 10,               // < 10
[Op.lte]: 10,              // <= 10
[Op.ne]: 20,               // != 20
[Op.eq]: 3,                // = 3
[Op.is]: null              // IS NULL
[Op.not]: true,            // IS NOT TRUE
[Op.between]: [6, 10],     // BETWEEN 6 AND 10
[Op.notBetween]: [11, 15], // NOT BETWEEN 11 AND 15
[Op.in]: [1, 2],           // IN [1, 2]
[Op.notIn]: [1, 2],        // NOT IN [1, 2]
[Op.like]: '%hat',         // LIKE '%hat'
[Op.notLike]: '%hat'       // NOT LIKE '%hat'
[Op.iLike]: '%hat'         // ILIKE '%hat' (case insensitive) (PG only)
[Op.notILike]: '%hat'      // NOT ILIKE '%hat'  (PG only)
[Op.startsWith]: 'hat'     // LIKE 'hat%'
[Op.endsWith]: 'hat'       // LIKE '%hat'
[Op.substring]: 'hat'      // LIKE '%hat%'
[Op.regexp]: '^[h|a|t]'    // REGEXP/~ '^[h|a|t]' (MySQL/PG only)
[Op.notRegexp]: '^[h|a|t]' // NOT REGEXP/!~ '^[h|a|t]' (MySQL/PG only)
[Op.iRegexp]: '^[h|a|t]'    // ~* '^[h|a|t]' (PG only)
[Op.notIRegexp]: '^[h|a|t]' // !~* '^[h|a|t]' (PG only)
[Op.like]: { [Op.any]: ['cat', 'hat']}
                           // LIKE ANY ARRAY['cat', 'hat'] - also works for iLike and notLike
[Op.overlap]: [1, 2]       // && [1, 2] (PG array overlap operator)
[Op.contains]: [1, 2]      // @> [1, 2] (PG array contains operator)
[Op.contained]: [1, 2]     // <@ [1, 2] (PG array contained by operator)
[Op.any]: [2,3]            // ANY ARRAY[2, 3]::INTEGER (PG only)
[Op.col]: 'user.organization_id' // = "user"."organization_id", with dialect specific column identifiers, PG in this example
[Op.gt]: { [Op.all]: literal('SELECT 1') }
                          // > ALL (SELECT 1)
[Op.contains]: 2           // @> '2'::integer (PG range contains element operator)
[Op.contains]: [1, 2]      // @> [1, 2) (PG range contains range operator)
[Op.contained]: [1, 2]     // <@ [1, 2) (PG range is contained by operator)
[Op.overlap]: [1, 2]       // && [1, 2) (PG range overlap (have points in common) operator)
[Op.adjacent]: [1, 2]      // -|- [1, 2) (PG range is adjacent to operator)
[Op.strictLeft]: [1, 2]    // << [1, 2) (PG range strictly left of operator)
[Op.strictRight]: [1, 2]   // >> [1, 2) (PG range strictly right of operator)
[Op.noExtendRight]: [1, 2] // &< [1, 2) (PG range does not extend to the right of operator)
[Op.noExtendLeft]: [1, 2]  // &> [1, 2) (PG range does not extend to the left of operator)
ModelName.findAll({
  order: [
    ["firstColumn", "DESC"],
    ["secondColumn", "ASC"],
  ],
});
有关订购的更多详细信息,请查看官方文档
ModelName.findAll({
  offset: 5, // Skip the first five results
  limit: 5, // Return only five results
});
发送拉取请求以添加/修改此帖子。