Sequelize模型定義


定義

定義模型與表之間的映射,使用 define 方法.

Sequelize 會自動增加 createdAtupdated 屬性,這樣能知道一個實例的創建時間和最終修改時間.如果不想自動生成,可以到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.firstNamethis.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,updatesave操作時,認證會自動運行.也可以在實例中手動認證

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}] } ] }) 
 


作者:kayorl
鏈接:https://www.jianshu.com/p/a644e05503b0
來源:簡書
簡書著作權歸作者所有,任何形式的轉載都請聯系作者獲得授權並注明出處。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM