定義
定義模型與表之間的映射,使用 define 方法.
Sequelize 會自動增加 createdAt
和 updated
屬性,這樣能知道一個實例的創(chuàng)建時間和最終修改時間.如果不想自動生成,可以到configuration去看如何實現(xiàn).
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 將會為該列增加 非空 屬性
// 在查詢數(shù)據庫之前想檢車一個值是否為 空 ,看 validation 節(jié)
title: { type: Sequelize.STRING, allowNull: false},
// 創(chuàng)建兩個擁有相同屬性的值會拋出一個錯誤
// 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 屬性同時也是創(chuàng)建一個 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" },
// 創(chuàng)建外碼
bar_id: {
type: Sequelize.INTEGER,
references: {
// This is a reference to another model
model: Bar,
//被引用模型的 列名 (是列名,即 field 名)
key: 'id',
// 檢查外碼約束,只支持 PostgreSQL .
deferrable: Sequelize.Deferrable.INITIALLY_IMMEDIATE
}
}
})
數(shù)據類型
更詳細的可以上 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 方法是可能的,可以被用來保護與數(shù)據庫列相映射的屬性,還可以定義一些假
屬性
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
屬性不存在于數(shù)據庫模式中. 實際上,假屬性可以通過以下兩種方式來定義
- 通過模型的 getter 方法
- 或者通過使用帶有
VIRTUAL
數(shù)據類型的列, VIRTUAL 數(shù)據類型可以有 validation , 然而 virtual 數(shù)據類型的 getter 方法不行
注意在 fullName
的 getter 方法中引用的 this.firstName
和 this.lastName
會觸發(fā)各自的 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 方法 可以保護內部數(shù)據
/* 'title' 屬性的 getter 方法*/
function(){
return this.getDataValue('title');
}
/* 'title' 屬性的 setter 方法*/
function(){
return this.setDataValue('title',title.toString().toLowerCase());
}
認證 (Validation)
模型認證, 可以規(guī)定模型中每個屬性的格式/內容 的認證. 其實現(xiàn)在這
當進行 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
}
}
}
}
});
注意當多個參數(shù)需要被傳遞到內嵌的認證函數(shù)時,多個參數(shù)應該被放在一個數(shù)組中.
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獲取更多細節(jié)
認證器和 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,
//不刪除數(shù)據庫中原有項, 增加新屬性 deletedAt 并設置為 當前日期,
//只有 TIMESTAMP 屬性是允許的時候有效
paranoid: true,
// 不要使用駝峰式語法,用下劃線代替
// so updatedAt will be updated_at
underscored: true,
// 不允許調整表名 ;
// 默認地, sequelize 會自動轉換所有傳遞的模型名字(define 的第一個參數(shù))
// 為復數(shù)
// 如果不想這樣,設置為 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
})
})
數(shù)據庫同步
開始一個新項目的時候,我們沒有數(shù)據庫架構,于是我們不需要 Sequelize.
只需要說明我們的模型結構, 讓庫做剩下的部分,現(xiàn)在只支持 表的創(chuàng)建與刪除
// 只同步還沒在數(shù)據庫中的模型
// Sync all models that aren't already in the database
sequelize.sync()
// 強制同步所有數(shù)據庫的模型
sequelize.sync({force: true})
// 刪除所有表
sequelize.drop()
// 開始執(zhí)行
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()
時被創(chuàng)建.
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}]
}
]
})