- Sequelize(2) 定义表格
- Sequelize(2) 定义表格
- 表格
- 表格
- 2-12. 表格标签中的其他标签
- html5表格标签
- sequelize-auto
- 2-13. 表格的结构
- koa2+sequelize初探
- sequelize的实例化/Model的定义、使用
定义
定义模型与表之间的映射,使用 define 方法.
Sequelize 会自动增加
createdAt
和updated
属性,这样能知道一个实例的创建时间和最终修改时间.如果不想自动生成,可以到configuration去看如何实现.var Project = sequelize.define('project', { title: Sequelize.STRING, description: Sequelize.TEXT }) var Task = sequelize.define('task', { title: Sequelize.STRING, description: Sequelize.TEXT, deadline: Sequelize.DATE })
还可以为每一个列增加一些可选属性
var Foo = sequelize.define('foo', { // 自动设置默认值为 true flag: { type: Sequelize.BOOLEAN, allowNull: false, defaultValue: true}, // 日期默认值 => 当前时间 myDate: { type: Sequelize.DATE, defaultValue: Sequelize.NOW }, // 设置列的 allowNull为 false 将会为该列增加 非空 属性 // 在查询数据库之前想检车一个值是否为 空 ,看 validation 节 title: { type: Sequelize.STRING, allowNull: false}, // 创建两个拥有相同属性的值会抛出一个错误 // 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. someUnique: {type: Sequelize.STRING, unique: true}, uniqueOne: { type: Sequelize.STRING, unique: 'compositeIndex'}, uniqueTwo: { type: Sequelize.INTEGER, unique: 'compositeIndex'} // unique 属性同时也是创建一个 unique 索引 的简写 someUnique: {type: Sequelize.STRING, unique: true} // 跟下面的两句定义语句等价 {someUnique: {type: Sequelize.STRING}}, {indexes: [{unique: true, fields: ['someUnique']}]} // 主码 identifier: { type: Sequelize.STRING, primaryKey: true}, // 自增 incrementMe: { type: Sequelize.INTEGER, autoIncrement: true }, // 注释,只有 MySQL 和 PG 可以使用 // Comments can be specified for each field for MySQL and PG hasComment: { type: Sequelize.INTEGER, comment: "I'm a comment!" }, // 在模型中的名字是小驼峰,在表中的列名可以用 field 属性来指定 fieldWithUnderscores: { type: Sequelize.STRING, field: "field_with_underscores" }, // 创建外码 bar_id: { type: Sequelize.INTEGER, references: { // This is a reference to another model model: Bar, //被引用模型的 列名 (是列名,即 field 名) key: 'id', // 检查外码约束,只支持 PostgreSQL . deferrable: Sequelize.Deferrable.INITIALLY_IMMEDIATE } } })
数据类型
更详细的可以上 DataTypes 看一看
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.GEOMETRY // Spatial column. PostgreSQL (with PostGIS) or MySQL only. Sequelize.GEOMETRY('POINT') // Spatial column with geomerty type. PostgreSQL (with PostGIS) or MySQL only. Sequelize.GEOMETRY('POINT', 4326) // Spatial column with geomerty type and SRID. PostgreSQL (with PostGIS) or MySQL only.
integer, bigint, float 和 double 同样支持 unsigned 和 zerofill 约束
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
对象标记的用法
// for enums: sequelize.define('model', { states: { type: Sequelize.ENUM, values: ['active', 'pending', 'deleted'] } })
Getters & Setters 方法
在模型中定义'对象-属性'的 getter 和 setter 方法是可能的,可以被用来保护与数据库列相映射的属性,还可以定义一些
假
属性
Getters 和 Setters 能以下面两种方式定义- 作为单个属性定义的一部分
- 作为模型可选的一部分
N.B: If a getter or setter is defined in both places then the function found in the relevant property definition will always take precedence.
定义为属性的一部分
var Employee = sequelize.define('employee', { name: { type : Sequelize.STRING, allowNull: false, get : function() { var title = this.getDataValue('title'); // 'this' 允许你去获得实例的属性 return this.getDataValue('name') + ' (' + title + ')'; }, }, title: { type : Sequelize.STRING, allowNull: false, set : function(val) { this.setDataValue('title', val.toUpperCase()); } } }); Employee .create({ name: 'John Doe', title: 'senior engineer' }) .then(function(employee) { console.log(employee.get('name')); // John Doe (SENIOR ENGINEER) console.log(employee.get('title')); // SENIOR ENGINEER })
定义为模型的一部分
下面是一个在模型内定义 getter 和 setter 方法的例子. 在这个例子里,
fullname
的 getter 方法是在模型内定义假属性
的一个例子
,因为fullname
属性不存在于数据库模式中. 实际上,假属性可以通过以下两种方式来定义- 通过模型的 getter 方法
- 或者通过使用带有
VIRTUAL
数据类型的列, VIRTUAL 数据类型可以有 validation , 然而 virtual 数据类型的 getter 方法不行
注意在
fullName
的 getter 方法中引用的this.firstName
和this.lastName
会触发各自的 getter 方法var Foo = sequelize.define('foo', { firstname: Sequelize.STRING, lastname: Sequelize.STRING }, { getterMethods : { fullName : function() { return this.firstname + ' ' + this.lastname } }, setterMethods : { fullName : function(value) { var names = value.split(' '); this.setDataValue('firstname', names.slice(0, -1).join(' ')); this.setDataValue('lastname', names.slice(-1).join(' ')); }, } });
在 getter 和 setter 方法中使用的 Helper 方法
- 获取一个基础属性值 , 经常用
this.getDataValue()
- 设置一个基础属性值 , 经常用
this.setDataValue()
- 坚持使用 getter 和 setter 方法 可以保护内部数据
/* 'title' 属性的 getter 方法*/ function(){ return this.getDataValue('title'); } /* 'title' 属性的 setter 方法*/ function(){ return this.setDataValue('title',title.toString().toLowerCase()); }
认证 (Validation)
模型认证, 可以规定模型中每个属性的格式/内容 的认证. 其实现在这
当进行
create
,update
和save
操作时,认证会自动运行.也可以在实例中手动认证var 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 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 min: 23, // only allow values >= 23 isArray: true, // only allow arrays isCreditCard: true, // check for valid credit card numbers // custom validations are also possible: isEven: function(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 } } } } });
注意当多个参数需要被传递到内嵌的认证函数时,多个参数应该被放在一个数组中.
isIn: [['en', 'zh']], // check the value is one of these
不用 validator.js 提供的错误信息,自己定制错误信息
isIn: { args: [['en', 'zh']], msg: "Must be English or Chinese" }
可以看validator.js PROJECT获取更多细节
认证器和
allowNull
如果模型的列被设置为
allowNull:true
和 值被设置为null
的话,那认证器不会运行.举个栗子, 一个字符串的列长度设置为 最短为5, 但它可以存储 null
模型认证
var Pub = Sequelize.define('pub', { name: { type: Sequelize.STRING }, address: { type: Sequelize.STRING }, latitude: { type: Sequelize.INTEGER, allowNull: true, defaultValue: null, validate: { min: -90, max: 90 } }, longitude: { type: Sequelize.INTEGER, allowNull: true, defaultValue: null, validate: { min: -180, max: 180 } }, }, { //在这里对模型进行验证,只有 latitude 和 longtitude 同时被给予或都为空时成立 validate: { bothCoordsOrNone: function() { if ((this.latitude === null) !== (this.longitude === null)) { throw new Error('Require either both latitude and longitude or neither') } } } })
配置
var Bar = sequelize.define('bar', { /* bla */ }, { // 不增加 TIMESTAMP 属性 (updatedAt, createdAt) timestamps: false, //不删除数据库中原有项, 增加新属性 deletedAt 并设置为 当前日期, //只有 TIMESTAMP 属性是允许的时候有效 paranoid: true, // 不要使用驼峰式语法,用下划线代替 // so updatedAt will be updated_at underscored: true, // 不允许调整表名 ; // 默认地, sequelize 会自动转换所有传递的模型名字(define 的第一个参数) // 为复数 // 如果不想这样,设置为 true freezeTableName: true, // 定义表名 tableName: 'my_very_custom_table_name' })
修改引擎
var Person = sequelize.define('person', { /* attributes */ }, { engine: 'MYISAM' }) // or globally var sequelize = new Sequelize(db, user, pw, { define: { engine: 'MYISAM' } })
做注释
var Person = sequelize.define('person', { /* attributes */ }, { comment: "I'm a table comment!" })
导入
可以把对表的定义放在单一文件中,返回对象恰好跟在 import 方法中定义的一样
// in your server file - e.g. app.js var Project = sequelize.import(__dirname + "/path/to/models/project") // 定义在 project.js 文件中已经定义完成了 // DataTypes 与上面解释的部分很像 module.exports = function(sequelize, DataTypes) { return sequelize.define("project", { name: DataTypes.STRING, description: DataTypes.TEXT }) } sequelize.import('project', function(sequelize, DataTypes) { return sequelize.define("project", { name: DataTypes.STRING, description: DataTypes.TEXT }) })
数据库同步
开始一个新项目的时候,我们没有数据库架构,于是我们不需要 Sequelize.
只需要说明我们的模型结构, 让库做剩下的部分,现在只支持
表的创建与删除
// 只同步还没在数据库中的模型 // Sync all models that aren't already in the database sequelize.sync() // 强制同步所有数据库的模型 sequelize.sync({force: true}) // 删除所有表 sequelize.drop() // 开始执行 sequelize.[sync|drop]().then(function() { // woot woot }).catch(function(error) { // whooops })
因为
.sync({force: true})
是毁灭性的操作, 可以使用 match 选项去增加更多的安全检查(正则)// 删除以 '_test' 结尾的词 sequelize.sync({ force: true, match: /_test$/ });
模型的扩展
Sequelize 允许我们去给 模型和相应的实例 传递定制方法
var sequelize = new Sequelize('database', 'username', 'password', { // 其他可选的初始化可以放在这里 define: { classMethods: { method1: function() {}, method2: function() {} }, instanceMethods: { method3: function() {} } } }) // Example: var Foo = sequelize.define('foo', { /* attributes */}); Foo.method1() Foo.method2() Foo.build().method3()
索引
Sequelize 支持在模型定义中增加索引, 这些索引在
Model.sync()
或sequelize.sync()
时被创建.sequelize.define('user', {}, { 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 a ordered field { name: 'title_index', method: 'BTREE', fields: ['author', {attribute: 'title', collate: 'en_US', order: 'DESC', length: 5}] } ] })
网友评论