sequelizejs中文文档(二)Model定义
Model定义
用define方法来定义模型与表之间的映射关系。
const Project = sequelize.define('project', { title: Sequelize.STRING, description: Sequelize.TEXT }) const Task = sequelize.define('task', { title: Sequelize.STRING, description: Sequelize.TEXT, deadline: Sequelize.DATE })
你还可以在每列上设置一些选项:
const Foo = sequelize.define('foo', { // instantiating will automatically set the flag to true if not set flag: { type: Sequelize.BOOLEAN, allowNull: false, defaultValue: true }, // default values for dates => current time myDate: { type: Sequelize.DATE, defaultValue: Sequelize.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: Sequelize.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: Sequelize.STRING, unique: 'compositeIndex' }, uniqueTwo: { type: Sequelize.INTEGER, unique: 'compositeIndex' }, // The unique property is simply a shorthand to create a unique constraint. someUnique: { type: Sequelize.STRING, unique: true }, // It's exactly the same as creating the index in the model's options. { someUnique: { type: Sequelize.STRING } }, { indexes: [ { unique: true, fields: [ 'someUnique' ] } ] }, // Go on reading for further information about primary keys identifier: { type: Sequelize.STRING, primaryKey: true }, // autoIncrement can be used to create auto_incrementing integer columns incrementMe: { type: Sequelize.INTEGER, autoIncrement: true }, // You can specify a custom field name via the 'field' attribute: fieldWithUnderscores: { type: Sequelize.STRING, field: 'field_with_underscores' }, // It is possible to create foreign keys: bar_id: { type: Sequelize.INTEGER, references: { // This is a reference to another model model: Bar, // This is the column name of the referenced model key: 'id', // This declares when to check the foreign key constraint. PostgreSQL only. deferrable: Sequelize.Deferrable.INITIALLY_IMMEDIATE } } })
Timestamps
默认情况下,Sequelize会将createdAt和updatedAt的属性添加到模型中,以便您可以知道数据库条目何时进入数据库以及何时被更新。
请注意,如果您使用Sequelize迁移,则需要将createdAt和updatedAt字段添加到迁移定义中:
module.exports = { up(queryInterface, Sequelize) { return queryInterface.createTable('my-table', { id: { type: Sequelize.INTEGER, primaryKey: true, autoIncrement: true, }, // Timestamps createdAt: Sequelize.DATE, updatedAt: Sequelize.DATE, }) }, down(queryInterface, Sequelize) { return queryInterface.dropTable('my-table'); }, }
如果您不想在模型上使用时间戳,只需要一些时间戳,或者您正在使用现有的数据库,其中列被命名为别的东西,请直接跳转到配置,以了解如何执行此操作。
Data types
以下是sequelizejs所支持的一些数据类型。 有关完整和更新的列表,请参阅数据类型。
Sequelize.STRING // VARCHAR(255) Sequelize.STRING(1234) // VARCHAR(1234) Sequelize.STRING.BINARY // VARCHAR BINARY Sequelize.TEXT // TEXT Sequelize.TEXT('tiny') // TINYTEXT Sequelize.INTEGER // INTEGER Sequelize.BIGINT // BIGINT Sequelize.BIGINT(11) // BIGINT(11) Sequelize.FLOAT // FLOAT Sequelize.FLOAT(11) // FLOAT(11) Sequelize.FLOAT(11, 12) // FLOAT(11,12) Sequelize.REAL // REAL PostgreSQL only. Sequelize.REAL(11) // REAL(11) PostgreSQL only. Sequelize.REAL(11, 12) // REAL(11,12) PostgreSQL only. Sequelize.DOUBLE // DOUBLE Sequelize.DOUBLE(11) // DOUBLE(11) Sequelize.DOUBLE(11, 12) // DOUBLE(11,12) Sequelize.DECIMAL // DECIMAL Sequelize.DECIMAL(10, 2) // DECIMAL(10,2) Sequelize.DATE // DATETIME for mysql / sqlite, TIMESTAMP WITH TIME ZONE for postgres Sequelize.DATE(6) // DATETIME(6) for mysql 5.6.4+. Fractional seconds support with up to 6 digits of precision Sequelize.DATEONLY // DATE without time. Sequelize.BOOLEAN // TINYINT(1) Sequelize.ENUM('value 1', 'value 2') // An ENUM with allowed values 'value 1' and 'value 2' Sequelize.ARRAY(Sequelize.TEXT) // Defines an array. PostgreSQL only. Sequelize.JSON // JSON column. PostgreSQL only. Sequelize.JSONB // JSONB column. PostgreSQL only. Sequelize.BLOB // BLOB (bytea for PostgreSQL) Sequelize.BLOB('tiny') // TINYBLOB (bytea for PostgreSQL. Other options are medium and long) Sequelize.UUID // UUID datatype for PostgreSQL and SQLite, CHAR(36) BINARY for MySQL (use defaultValue: Sequelize.UUIDV1 or Sequelize.UUIDV4 to make sequelize generate the ids automatically) Sequelize.RANGE(Sequelize.INTEGER) // Defines int4range range. PostgreSQL only. Sequelize.RANGE(Sequelize.BIGINT) // Defined int8range range. PostgreSQL only. Sequelize.RANGE(Sequelize.DATE) // Defines tstzrange range. PostgreSQL only. Sequelize.RANGE(Sequelize.DATEONLY) // Defines daterange range. PostgreSQL only. Sequelize.RANGE(Sequelize.DECIMAL) // Defines numrange range. PostgreSQL only. Sequelize.ARRAY(Sequelize.RANGE(Sequelize.DATE)) // Defines array of tstzrange ranges. PostgreSQL only. Sequelize.GEOMETRY // Spatial column. PostgreSQL (with PostGIS) or MySQL only. Sequelize.GEOMETRY('POINT') // Spatial column with geometry type. PostgreSQL (with PostGIS) or MySQL only. Sequelize.GEOMETRY('POINT', 4326) // Spatial column with geometry type and SRID. PostgreSQL (with PostGIS) or MySQL only.
BLOB数据类型允许您将数据作为字符串和缓冲区插入。 当您在具有BLOB列的模型上执行find或findAll时,该数据将始终作为缓冲区返回。
如果您正在使用PostgreSQL TIMESTAMP WITHOUT TIMEZONE,您需要将其解析为不同的时区,请使用pg库自己的解析器:
require('pg').types.setTypeParser(1114, stringValue => { return new Date(stringValue + '+0000'); // e.g., UTC offset. Use any offset that you would like. });
除了上述类型之外,integer,bigint,float和double也支持unsigned和zerofill属性,可以按任意顺序组合:注意这不适用于PostgreSQL!
Sequelize.INTEGER.UNSIGNED // INTEGER UNSIGNED Sequelize.INTEGER(11).UNSIGNED // INTEGER(11) UNSIGNED Sequelize.INTEGER(11).ZEROFILL // INTEGER(11) ZEROFILL Sequelize.INTEGER(11).ZEROFILL.UNSIGNED // INTEGER(11) UNSIGNED ZEROFILL Sequelize.INTEGER(11).UNSIGNED.ZEROFILL // INTEGER(11) UNSIGNED ZEROFILL
Range types
由于范围类型具有其绑定的包含/排除的额外信息,所以使用一个元组在javascript中表示它们并不是很简单。
将范围提供为值时,您可以从以下API中进行选择:
// defaults to '["2016-01-01 00:00:00+00:00", "2016-02-01 00:00:00+00:00")' // inclusive lower bound, exclusive upper bound Timeline.create({ range: [new Date(Date.UTC(2016, 0, 1)), new Date(Date.UTC(2016, 1, 1))] }); // control inclusion const range = [new Date(Date.UTC(2016, 0, 1)), new Date(Date.UTC(2016, 1, 1))]; range.inclusive = false; // '()' range.inclusive = [false, true]; // '(]' range.inclusive = true; // '[]' range.inclusive = [true, false]; // '[)' // or as a single expression const range = [ { value: new Date(Date.UTC(2016, 0, 1)), inclusive: false }, { value: new Date(Date.UTC(2016, 1, 1)), inclusive: true }, ]; // '("2016-01-01 00:00:00+00:00", "2016-02-01 00:00:00+00:00"]' // composite form const range = [ { value: new Date(Date.UTC(2016, 0, 1)), inclusive: false }, new Date(Date.UTC(2016, 1, 1)), ]; // '("2016-01-01 00:00:00+00:00", "2016-02-01 00:00:00+00:00")' Timeline.create({ range });
不过请注意,只要您收到范围内的值,您将收到:
// stored value: ("2016-01-01 00:00:00+00:00", "2016-02-01 00:00:00+00:00"] range // [Date, Date] range.inclusive // [false, true]
确保在序列化之前将其转换为可序列化的格式,因为数组额外的属性将不会被序列化。
Special Cases
// empty range: Timeline.create({ range: [] }); // range = 'empty' // Unbounded range: Timeline.create({ range: [null, null] }); // range = '[,)' // range = '[,"2016-01-01 00:00:00+00:00")' Timeline.create({ range: [null, new Date(Date.UTC(2016, 0, 1))] }); // Infinite range: // range = '[-infinity,"2016-01-01 00:00:00+00:00")' Timeline.create({ range: [-Infinity, new Date(Date.UTC(2016, 0, 1))] });
Getters & setters
可以在模型上定义“object-property”getter和setter函数,这些可以用于映射到数据库字段的“protecting”属性,也可以用于定义“pseudo”属性。
Getters和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 })
作为模型选项的一部分
const Foo = sequelize.define('foo', { firstname: Sequelize.STRING, lastname: Sequelize.STRING }, { getterMethods: { fullName() { return this.firstname + ' ' + this.lastname } }, setterMethods: { fullName(value) { const names = value.split(' '); this.setDataValue('firstname', names.slice(0, -1).join(' ')); this.setDataValue('lastname', names.slice(-1).join(' ')); }, } });
Validations
模型验证,允许您为模型的每个属性指定格式/内容/继承验证。
验证将自动运行在创建,更新和保存。 您也可以调用validate()手动验证一个实例。
const ValidateMe = sequelize.define('foo', { foo: { 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 poem 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 // custom validations are also possible: isEven(value) { if (parseInt(value) % 2 != 0) { throw new Error('Only even values are allowed!') // we also are in the model's context here, so this.otherField // would get the value of otherField if it existed } } } } });
Configuration
const Bar = sequelize.define('bar', { /* bla */ }, { // don't add the timestamp attributes (updatedAt, createdAt) timestamps: false, // don't delete database entries but set the newly added attribute deletedAt // to the current date (when deletion was done). paranoid will only work if // timestamps are enabled paranoid: true, // don't use camelcase for automatically added attributes but underscore style // so updatedAt will be updated_at underscored: true, // disable the modification of table names; By default, sequelize will automatically // transform all passed model names (first parameter of define) into plural. // if you don't want that, set the following freezeTableName: true, // define the table's name tableName: 'my_very_custom_table_name', // Enable optimistic locking. When enabled, sequelize will add a version count attribute // to the model and throw an OptimisticLockingError error when stale instances are saved. // Set to true or a string with the attribute name you want to use to enable. version: true })
const Foo = sequelize.define('foo', { /* bla */ }, { // don't forget to enable timestamps! timestamps: true, // I don't want createdAt createdAt: false, // I want updatedAt to actually be called updateTimestamp updatedAt: 'updateTimestamp', // And deletedAt to be called destroyTime (remember to enable paranoid for this to work) deletedAt: 'destroyTime', paranoid: true })
Import
您还可以使用导入方法将模型定义存储在单个文件中。 返回的对象与导入文件的功能中定义的完全相同。 自从Sequelize v1:5.0以来,导入被缓存,所以当调用文件导入两次或更多次时,不会遇到麻烦。
// in your server file - e.g. app.js const Project = sequelize.import(__dirname + "/path/to/models/project") // The model definition is done in /path/to/models/project.js // As you might notice, the DataTypes are the very same as explained above module.exports = (sequelize, DataTypes) => { return sequelize.define("project", { name: DataTypes.STRING, description: DataTypes.TEXT }) }
导入方法也可以接受回调作为参数。
sequelize.import('project', (sequelize, DataTypes) => { return sequelize.define("project", { name: DataTypes.STRING, description: DataTypes.TEXT }) })