Model
相當於數據庫中表,有時它也會被稱爲“模型”或“工廠”。Model
不能通過構造函數創建,而只能通過sequlize.define
方法來定義或通過sequlize.import
導入。通過define
定義一個Model
,就相當於定義了一種模型與數據表之間的映射關係,通過模型可以實現對錶記錄的增、刪、改、查等操作。
- 定義描述
- 模型的使用
Model
類的API- 3.1
removeAttribute()
- 移除屬性 - 3.2
sync()
- 同步模型到數據庫 - 3.3
drop()
- 刪除數據庫中的表 - 3.4
schema()
- 指定schema
- 3.5
getTableName()
- 獲取表名 - 3.6
addScope()
- 添加限制範圍 - 3.7
scope()
- 應用限制範圍 - 3.8
findAll()
- 查詢多條數據 - 3.9
findById()
- 通過Id查詢單條數據 - 3.10
findOne()
- 通過單條數據 - 3.11
aggregate()
- 聚合查詢 - 3.12
count()
- 統計查詢結果數 - 3.13
findAndCount()
- 分頁查詢 - 3.14
max()
- 查詢最大值 - 3.15
min()
- 查詢最大值 - 3.16
sum()
- 求和 - 3.17
build()
- 創建新實例 - 3.18
create()
- 創建保存新實例 - 3.19
findOrInitialize()
- 查找或初始化 - 3.20
findOrCreate()
- 查找或創建 - 3.21
findCreateFind()
- 查找或創建 - 3.22
upsert()
- 創建或更新 - 3.23
bulkCreate()
- 創建多條記錄 - 3.24
truncate()
- 截斷模型 - 3.25
destroy()
- 刪除記錄 - 3.26
restore()
- 恢復記錄 - 3.27
update()
- 更新記錄 - 3.28
describe()
- 查詢表信息
- 3.1
1. 定義描述
1.1 Definition - 模型定義
定義模型model
和表之間的映射關係使用define
方法。定義時Sequelize會自動爲其添加createdAt
和updatedAt
兩個屬性(屬性相當於表中的字段),這樣你就可以知道數據什麼時候插入了數據庫和什麼時候進行了更新。
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 後,會爲列添加 NOT NULL 非空限制 // 這意味着當執行查詢(插入/更新)時相關字段爲空會從數據庫層拋出錯誤 // 如果想在執行查詢時進行值檢測,請參考“驗證”一節 title: { type: Sequelize.STRING, allowNull: false}, // 添加唯一(unique)約束後插入重複值會報錯 // unique屬性可以是boolean 或 string類型 // 如果爲多個字段添加了相同的字符串那麼將會是一個符合唯一鍵 someUnique: {type: Sequelize.STRING, unique: true}, uniqueOne: { type: Sequelize.STRING, unique: 'compositeIndex'}, uniqueTwo: { type: Sequelize.INTEGER, unique: 'compositeIndex'} // unique屬性以一個簡單的簡寫方式創建唯一索引 someUnique: {type: Sequelize.STRING, unique: true} // 同樣的,也可以模型的選項中創建索引 {someUnique: {type: Sequelize.STRING}}, {indexes: [{unique: true, fields: ['someUnique']}]} // 定義一個主鍵 identifier: { type: Sequelize.STRING, primaryKey: true}, // autoIncrement 選項用於創建一個自增的整型列 incrementMe: { type: Sequelize.INTEGER, autoIncrement: true }, // Comments 可以在MySQL 和 PG中指定定段描述 hasComment: { type: Sequelize.INTEGER, comment: "I'm a comment!" }, // 可以通過 "field" 屬性來指定數據庫中的字段名 fieldWithUnderscores: { type: Sequelize.STRING, field: "field_with_underscores" }, // 通過references選項可以創建外鍵: bar_id: { type: Sequelize.INTEGER, references: { // 引用另一個模型 model: Bar, // 連接模型的列表 key: 'id', // 強制使用外鍵約束,僅適用於 PostgreSQL deferrable: Sequelize.Deferrable.INITIALLY_IMMEDIATE } } })
如果你不想在模型中使用時間戳,而只需要一些時間;或者你正在使用一個已經存在的數據庫,而其中的列名與你的所需要並不一致。更多配置請參考模型配置。
1.2 Data types - 數據類型
在定義模型時,我們會指定其屬性(字段)的數據類型,下面是Sequelize中支持數據類型及其與數據庫中字段類型的對應關係:
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 // PostgreSQL 和 SQLite 中爲 UUID, MySQL 中爲CHAR(36) BINARY (使用 defaultValue: Sequelize.UUIDV1 或 Sequelize.UUIDV4 生成默認值) 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 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.
BLOB
類型中你可以插入字符串或二進制buffer
,在進行查詢時其總是會返回buffer
。
如果要使用PostgreSQL的TIMESTAMP WITHOUT TIME ZONE
類型,那麼你需要存入一個不同的時區,並使用pg
庫進行轉換
require('pg').types.setTypeParser(1114, function(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.define('model', { states: { type: Sequelize.ENUM, values: ['active', 'pending', 'deleted'] } })
1.3 Deferrable - 延時執行
當你指定一個可選的外鍵列,那麼可以在PostgreSQL定義爲Deferrable
類型。以下選項可用:
// Defer all foreign key constraint check to the end of a transaction Sequelize.Deferrable.INITIALLY_DEFERRED // Immediately check the foreign key constraints Sequelize.Deferrable.INITIALLY_IMMEDIATE // Don't defer the checks at all Sequelize.Deferrable.NOT
1.4 Getters & setters - 訪問器&設置器
可以在你的模型中將對象屬性定義爲訪問/設置函數
訪問器&設置器有以下兩種定義方式:
- 做爲一個屬性定義
- 做爲模型選項
做爲一個屬性定義
var Employee = sequelize.define('employee', { name: { type : Sequelize.STRING, allowNull: false, get : function() { var 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 : 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 })
做爲模型選項
在下面的示例中,定義了一個名爲fullName
的訪問器,它是對this.firstname
和this.lastname
兩個屬性引用,這個屬性的一個假屬性它並不是數據庫中的一部分。定義假屬性
可以使用訪問器或定義爲VIRTUAL
類型兩種方式,Virtual
類型可以驗證而訪問器則不能。
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(' ')); }, } });
訪問器&設置器內部定義的幫助函數:
檢索底層屬性值-總是使用this.getDataValue()
/* 訪問 'title' 的屬性 */ function() { return this.getDataValue('title'); }
設置底層屬性值-總是使用this.setDataValue()
/* 設置 'title' 的屬性 */ function() { return this.setDataValue('title', title.toString().toLowerCase()); }
1.5 Validations - 驗證
模型驗證,讓我們可以模型的每個屬性執行驗證。
我們通過模型列屬性的validate
屬性來添加驗證,這些驗證會在模型實例執行create
、update
和save
自動執行。也可以通過instance.validate()
方法,來手工驗證模型實例。
var ValidateMe = sequelize.define('foo', { foo: { type: Sequelize.STRING, validate: { is: ["^[a-z]+$",'i'], // 只允許字母 is: /^[a-z]+$/i, // 只允許字母 not: ["[a-z]",'i'], // 不能使用字母 isEmail: true, // 檢測郵箱格式 ([email protected]) isUrl: true, // 檢查Url格式 (http://foo.com) isIP: true, // 檢查 IPv4 或 IPv6 格式 isIPv4: true, // 檢查 IPv4 isIPv6: true, // 檢查 IPv6 isAlpha: true, // 不能使用字母 isAlphanumeric: true, // 只允許字母數字字符 isNumeric: true, // 只能使用數字 isInt: true, // 只能是整數 isFloat: true, // 只能是浮點數 isDecimal: true, // 檢查數字 isLowercase: true, // 檢查小寫字母 isUppercase: true, // 檢查大寫字母 notNull: true, // 不允許null isNull: true, // 只能爲null notEmpty: true, // 不能空字符串 equals: 'specific value', // 只能使用指定值 contains: 'foo', // 必須包含子字符串 notIn: [['foo', 'bar']], // 不能是數組中的任意一個值 isIn: [['foo', 'bar']], // 只能是數組中的任意一個值 notContains: 'bar', // 不能包含子字符串 len: [2, 10], // 值的長度必在 2 和 10 之間 isUUID: 4, // 只能是UUID isDate: true, // 只能是日期字符串 isAfter: "2011-11-05", // 只能使用指定日期之後的時間 isBefore: "2011-11-05", // 只能使用指定日期之前的時間 max: 23, // 允許的最大值 min: 23, // 允許的最小值 isArray: true, // 不能使用數組 isCreditCard: true, // 檢查是有效的信用卡 // 也可以自定義驗證: 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 } } } } });
驗證時可以使用自定義的錯誤信息代替validator.js
的默認信息,只需要在通過對象或數組的方式提供參數即可:
isInt: { msg: "Must be an integer number of pennies" }
或者參數中同樣需要提供args
屬性:
isIn: { args: [['en', 'zh']], msg: "Must be English or Chinese" }
模型驗證
Validations
同可以用於模型的檢測,只需要在字段定義之後定義驗證即可。如,在經緯度的應用的我們會需要latitude
和longitude
都不爲空或都爲空,這時我們可以像下面這樣驗證:
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 } }, }, { validate: { bothCoordsOrNone: function() { if ((this.latitude === null) !== (this.longitude === null)) { throw new Error('Require either both latitude and longitude or neither') } } } })
1.6 Configuration - 配置
定義模型時,可以通過配置來設置列名等相關信息:
var Bar = sequelize.define('bar', { /* bla */ }, { // 不要添加時間戳屬性 (updatedAt, createdAt) timestamps: false, // 不從數據庫中刪除數據,而只是增加一個 deletedAt 標識當前時間 // paranoid 屬性只在啓用 timestamps 時適用 paranoid: true, // 不使用駝峯式命令規則,這樣會在使用下劃線分隔 // 這樣 updatedAt 的字段名會是 updated_at underscored: true, // 禁止修改表名. 默認情況下 // sequelize會自動使用傳入的模型名(define的第一個參數)做爲表名 // 如果你不想使用這種方式你需要進行以下設置 freezeTableName: true, // 定義表名 tableName: 'my_very_custom_table_name' })
如果你想sequelize處理時間戳,但只在個別情況下使用,那麼你可以對使用的列單獨重載:
var Foo = sequelize.define('foo', { /* bla */ }, { // 不要忘了啓用 timestamps timestamps: true, // 不想使用 createdAt createdAt: false, // 想 updatedAt 的實際名爲 'updateTimestamp' updatedAt: 'updateTimestamp' // 要將 deletedAt 設置爲 destroyTime (注意要啓用paranoid) deletedAt: 'destroyTime', paranoid: true })
配置時,也可以修改數據庫引擎。如,將默認的InnoDB修改爲MyISAM:
var Person = sequelize.define('person', { /* attributes */ }, { engine: 'MYISAM' }) // or globally var sequelize = new Sequelize(db, user, pw, { define: { engine: 'MYISAM' } })
或者指定一個表描述(MySql和PG中):
var Person = sequelize.define('person', { /* attributes */ }, { comment: "I'm a table comment!" })
注意:字段attributes
同樣可以添加comment
屬性,但出於兼容性考慮自sequelize V1.7+
起已不再將此屬性同步到數據庫中,但爲字段添加這個屬性依然是增加可讀性的不錯的方式。
1.7 Import - 模型導入
我們可以將模型定義爲一個單獨的文件,並通過
導入。通過文件導入返回的對象與通過defined
方法定義的模型完全一致,兩者都是instance
模型實例。自v1.5.0
起,sequlize會對導入進行緩存,這樣就不用擔心多次對文件修改造成的一些問題。
如,我們在project.js
文件中定義一個名爲project
的模型:
// 這個文件定義於 /path/to/models/project.js module.exports = function(sequelize, DataTypes) { return sequelize.define("project", { name: DataTypes.STRING, description: DataTypes.TEXT }) }
我們可以app.js
或其它需要的地方引入定義的模型:
var Project = sequelize.import(__dirname + "/path/to/models/project")
import
同樣可以使用回調函數參數的使用方式:
sequelize.import('project', function(sequelize, DataTypes) { return sequelize.define("project", { name: DataTypes.STRING, description: DataTypes.TEXT }) })
1.8 Database synchronization - 數據庫同步
開始一個新項目時,我們並沒有數據庫結構,使用Sequelize
時,並不需要先定義好數據庫結構。我們只要定義好模型,然後進行同步即可。
Sequelize
支持創建表和刪除表:
// 通過 sync 方法同步數據結構 // 即,創建表 Project.sync() Task.sync() // 強制創建 // 通過設置 force 屬性會首先刪除表並重新創建 Project.sync({force: true}) // 刪除表 Project.drop() Task.drop() // 事件處理 Project.[sync|drop]().then(function() { // 處理成功 }).catch(function(error) { // 出了點問題^~^ })
.sync({ force: true })
會刪除並重建表,這時我們可以添加match
選項,只重建正則表達式匹配的表:
sequelize.sync({ force: true, match: /_test$/ });
1.9 Expansion of models - 模型擴展
開始一個新項目時,我們並沒有數據庫結構,使用Sequelize
時,並不需要先定義好數據庫結構。我們只要定義好模型,然後進行同步即可。
自定義方法
Sequelize
允許我們爲實例添加自定義方法,可以像下面這樣定義:
var Foo = sequelize.define('foo', { /* attributes */}, { classMethods: { method1: function(){ return 'smth' } }, instanceMethods: { method2: function() { return 'foo' } } }) // Example: Foo.method1() Foo.build().method2()
虛擬訪問器
也可以設置虛擬訪問器:
var User = sequelize.define('user', { firstname: Sequelize.STRING, lastname: Sequelize.STRING }, { instanceMethods: { getFullname: function() { return [this.firstname, this.lastname].join(' ') } } }) // Example: User.build({ firstname: 'foo', lastname: 'bar' }).getFullname() // 'foo bar'
全局方法
還可以定義用於所有模型實例的全局方法:
var sequelize = new Sequelize('database', 'username', 'password', { // Other options during the initialization could be here 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}] } ] })
2. 模型的使用
2.1 Data retrieval / Finders - 數據索引/查找
查找方法是爲了從數據庫中查詢數據,這些方法不是返回原始數據對象,而是返回模型實例。因會其返回的是模型實例,所以在文檔的查詢結果中可以任意調用模型實例的成員、方法等。(更多實例介紹請參考:instance
)
下面是一些常用的查詢方法。
find
- 從數據庫中查找一個指定元素
// 按已知 id查找 Project.findById(123).then(function(project) { // project 是一個 Project 實例,且包含存儲在數據中的數據 // 當不存在 id 爲123的記錄時 project 爲 null }) // 按屬性查找 Project.findOne({ where: {title: 'aProject'} }).then(function(project) { // project 是匹配到的第一個 title 爲 'aProject' 的 Projects 或 null }) Project.findOne({ where: {title: 'aProject'}, attributes: ['id', ['name', 'title']] }).then(function(project) { // project 是匹配到的第一個 title 爲 'aProject' 的 Projects 或 null // project 的 project.title 屬性中會包含 'name' })
findOrCreate
- 從數據庫中查找一個指定元素如果不存在則創建記錄
findOrCreate
可用於檢測一個不確定是否存在的元素,如果存在則返回記錄,不存在時會使用提供的默認值新建記錄。
如,當數據不存在時,其執行效果如下:
User .findOrCreate({where: {username: 'itbilu.com'}, defaults: {job: 'Technical Lead JavaScript'}}) .spread(function(user, created) { console.log(user.get({ plain: true })) console.log(created) /* { username: 'itbilu.com', job: 'Technical Lead JavaScript', id: 1, createdAt: Fri Mar 22 2013 21: 28: 34 GMT + 0100(CET), updatedAt: Fri Mar 22 2013 21: 28: 34 GMT + 0100(CET) } created: true */ })
當數據存在時,會返回記錄:
User .create({ username: 'fnord', job: 'omnomnom' }) .then(function() { User .findOrCreate({where: {username: 'fnord'}, defaults: {job: 'something else'}}) .spread(function(user, created) { console.log(user.get({ plain: true })) console.log(created) /* { username: 'fnord', job: 'omnomnom', id: 2, createdAt: Fri Mar 22 2013 21: 28: 34 GMT + 0100(CET), updatedAt: Fri Mar 22 2013 21: 28: 34 GMT + 0100(CET) } created: false */ }) })
findAndCountAll
- 從數據庫中查找多個元素,返回數據與記錄總數
這個方法是findAll
和count
兩個方法的便捷形式,這在你想使用limit
和offset
進行分頁查詢時非常有用。
在返回值中,會包含以下兩個屬性:
count
- 整數,匹配到的總記錄數rows
- 對象數據,通過 limit 和 offset匹配的當前頁數據
Project .findAndCountAll({ where: { title: { $like: 'foo%' } }, offset: 10, limit: 2 }) .then(function(result) { console.log(result.count); console.log(result.rows); });
findAndCountAll
同樣支持使用include
包含,使用包含時只有將required
設置爲true纔會添加到count
部分:
User.findAndCountAll({ include: [ { model: Profile, required: true} ], limit: 3 });
使用include
時,兩個模型之間應該存在主/外鍵關係,如果不存在就應該在include
中手工建立連接。
在上面的示例中,爲Profile
設置了required
,所以在查詢時會使用INNER JOIN
內連接。
findAll
- 從數據庫中查找多個元素
findAndCountAll
中使用的查詢選項同樣適用於findAll
方法。
// 查詢多條記錄 Project.findAll().then(function(projects) { // projects 是一個包含Project實例的數組 }) // 同樣的,all是findAll的別名方法: Project.all().then(function(projects) { // projects 是一個包含Project實例的數組 }) // 通過指定屬性查找 Project.findAll({ where: { name: 'A Project' } }).then(function(projects) { // projects 是一個包含 Project 實例的數組 }) // 查詢時使用字符串替換 Project.findAll({ where: ["id > ?", 25] }).then(function(projects) { // projects 是一個包含 Project 實例的數組,各實例的id 大於25 }) // 查詢指定範圍 Project.findAll({ where: { id: [1,2,3] } }).then(function(projects) { // projects 是一個包含 Project 實例的數組,各實例id 是1, 2, 或 3 // 這在實例執行時,會使用 IN查詢 }) Project.findAll({ where: { id: { $and: {a: 5} // AND (a = 5) $or: [{a: 5}, {a: 6}] // (a = 5 OR a = 6) $gt: 6, // id > 6 $gte: 6, // id >= 6 $lt: 10, // id < 10 $lte: 10, // id <= 10 $ne: 20, // id != 20 $between: [6, 10], // BETWEEN 6 AND 10 $notBetween: [11, 15], // NOT BETWEEN 11 AND 15 $in: [1, 2], // IN [1, 2] $notIn: [1, 2], // NOT IN [1, 2] $like: '%hat', // LIKE '%hat' $notLike: '%hat' // NOT LIKE '%hat' $iLike: '%hat' // ILIKE '%hat' (case insensitive) (PG only) $notILike: '%hat' // NOT ILIKE '%hat' (PG only) $overlap: [1, 2] // && [1, 2] (PG array overlap operator) $contains: [1, 2] // @> [1, 2] (PG array contains operator) $contained: [1, 2] // <@ [1, 2] (PG array contained by operator) $any: [2,3] // ANY ARRAY[2, 3]::INTEGER (PG only) }, status: { $not: false, // status NOT FALSE } } })
IN/OR 等複合篩選
如果要在查詢中使用AND
、OR
或DOT
等篩選條件,可以查詢的where
中指定$and
、$or
或$not
等屬性:
Project.findOne({ where: { name: 'a project', $or: [ { id: [1,2,3] }, { id: { $gt: 10 } } ] } }) Project.findOne({ where: { name: 'a project', id: { $or: [ [1,2,3], { $gt: 10 } ] } } })
這個查詢生成的實際SQL語句爲:
SELECT * FROM `Projects` WHERE ( `Projects`.`name` = 'a project' AND (`Projects`.`id` IN (1,2,3) OR `Projects`.`id` > 10) ) LIMIT 1;
$not
示例:
Project.findOne({ where: { name: 'a project', $not: [ { id: [1,2,3] }, { array: { $contains: [3,4,5] } } ] } });
將生成以下語句:
SELECT * FROM `Projects` WHERE ( `Projects`.`name` = 'a project' AND NOT (`Projects`.`id` IN (1,2,3) OR `Projects`.`array` @> ARRAY[1,2,3]::INTEGER[]) ) LIMIT 1;
對數據集使用limit
、offset
、order
和 group
// 使用 limit 限制返回結果數 Project.findAll({ limit: 10 }) // 跳過前 10 條結果 Project.findAll({ offset: 10 }) // 跳過前 10 條結果後,返回兩條數據 Project.findAll({ offset: 10, limit: 2 })
分組與排序的語法是相似的,如下:
Project.findAll({order: 'title DESC'}) // ORDER BY title DESC Project.findAll({group: 'name'}) // GROUP BY name
傳入簡單的字符串時,查詢字符串會逐字查詢,即列名不轉義。如果需要列名轉義,可以提供一個數組參數。
something.findOne({ order: [ 'name', // will return `name` 'username DESC', // will return `username DESC` -- i.e. don't do it! ['username', 'DESC'], // will return `username` DESC sequelize.fn('max', sequelize.col('age')), // will return max(`age`) [sequelize.fn('max', sequelize.col('age')), 'DESC'], // will return max(`age`) DESC [sequelize.fn('otherfunction', sequelize.col('col1'), 12, 'lalala'), 'DESC'], // will return otherfunction(`col1`, 12, 'lalala') DESC [sequelize.fn('otherfunction', sequelize.fn('awesomefunction', sequelize.col('col'))), 'DESC'] // will return otherfunction(awesomefunction(`col`)) DESC, This nesting is potentially infinite! [{ raw: 'otherfunction(awesomefunction(`col`))' }, 'DESC'] // This won't be quoted, but direction will be added ] })
更多關於聚合查詢,請參考:在Sequelize中使用group by分組聚合查詢
原始查詢
默情況下,Sequlize人爲查詢結構創建實例,通過這個實例可以進行數據的更新、刪除等操作。有時候我只需要顯示數據集,而不需要進行處理,這時可以通過設置raw
選項來返回原始數據:
// 增加 raw 選項後,會返回數據庫中的原始結果 Project.findAll({ where: { ... }, raw: true })
count
- 統計數據庫中的元素數
count
可以統計數據庫中的元素數:
Project.count().then(function(c) { console.log("There are " + c + " projects!") }) Project.count({ where: ["id > ?", 25] }).then(function(c) { console.log("There are " + c + " projects with an id greater than 25.") })
max
- 查找指定表中最大值
// 數據庫中有3條記錄,年齡分別是 10, 5, 40 Project.max('age').then(function(max) { // 會返回 40 }) Project.max('age', { where: { age: { lt: 20 } } }).then(function(max) { // 會返回 10 })
min
- 查找指定表中最小值
// 數據庫中有3條記錄,年齡分別是 10, 5, 40 Project.min('age').then(function(min) { // 會返回 5 }) Project.min('age', { where: { age: { $gt: 5 } } }).then(function(min) { // 會返回 10 })
sum
- 對指定屬性求和
// 數據庫中有3條記錄,年齡分別是 10, 5, 40 Project.sum('age').then(function(sum) { // 會返回 55 }) Project.sum('age', { where: { age: { $gt: 5 } } }).then(function(sum) { // 會返回 50 })
2.2 Eager loading - 預加載
從數據庫中加載數據時,除數據本身外還想得到與之相關聯的數據-這就是所謂的預加載。也就是說,使用find
或findAll
查詢數據時,通過include
屬性同時加載關聯的數據。
假設有以下數據結構:
var User = sequelize.define('user', { name: Sequelize.STRING }) , Task = sequelize.define('task', { name: Sequelize.STRING }) , Tool = sequelize.define('tool', { name: Sequelize.STRING }) Task.belongsTo(User) User.hasMany(Task) User.hasMany(Tool, { as: 'Instruments' }) sequelize.sync().then(function() { // this is where we continue ... })
通過belongsTo
與hasMany
建立關係後,就可以像下面這樣查詢:
Task.findAll({ include: [ User ] }).then(function(tasks) { console.log(JSON.stringify(tasks)) /* [{ "name": "A Task", "id": 1, "createdAt": "2013-03-20T20:31:40.000Z", "updatedAt": "2013-03-20T20:31:40.000Z", "userId": 1, "user": { "name": "John Doe", "id": 1, "createdAt": "2013-03-20T20:31:45.000Z", "updatedAt": "2013-03-20T20:31:45.000Z" } }] */ })
由於Task
與User
是1對多的關係,所在以查詢時user
會做爲一個對象屬性被同時加載。
下面我們進行一個多對多的查詢:
User.findAll({ include: [ Task ] }).then(function(users) { console.log(JSON.stringify(users)) /* [{ "name": "John Doe", "id": 1, "createdAt": "2013-03-20T20:31:45.000Z", "updatedAt": "2013-03-20T20:31:45.000Z", "tasks": [{ "name": "A Task", "id": 1, "createdAt": "2013-03-20T20:31:40.000Z", "updatedAt": "2013-03-20T20:31:40.000Z", "userId": 1 }] }] */ })
在多對多的關係中,相關數據會做爲一個數組屬性被同時加載。
關聯查詢時,可以使用as
選項爲關係數據指定別名:
User.findAll({ include: [{ model: Tool, as: 'Instruments' }] }).then(function(users) { console.log(JSON.stringify(users)) /* [{ "name": "John Doe", "id": 1, "createdAt": "2013-03-20T20:31:45.000Z", "updatedAt": "2013-03-20T20:31:45.000Z", "Instruments": [{ "name": "Toothpick", "id": 1, "createdAt": null, "updatedAt": null, "userId": 1 }] }] */ })
關聯查詢時,同樣可以使用where
選項對關聯數據進行篩選:
User.findAll({ include: [{ model: Tool, as: 'Instruments', where: { name: { $like: '%ooth%' } } }] }).then(function(users) { console.log(JSON.stringify(users)) /* [{ "name": "John Doe", "id": 1, "createdAt": "2013-03-20T20:31:45.000Z", "updatedAt": "2013-03-20T20:31:45.000Z", "Instruments": [{ "name": "Toothpick", "id": 1, "createdAt": null, "updatedAt": null, "userId": 1 }] }], [{ "name": "John Smith", "id": 2, "createdAt": "2013-03-20T20:31:45.000Z", "updatedAt": "2013-03-20T20:31:45.000Z", "Instruments": [{ "name": "Toothpick", "id": 1, "createdAt": null, "updatedAt": null, "userId": 1 }] }], */ })
注意:使用include.where
條件時,include.requied
會被隱式的設置爲true
,即在查詢時會使用INNER JOIN
內連接。
全關聯
如果多個模型間存在關聯關係,而我們在查詢時又要查詢所有的數據,就可以設置all: true
來關聯所有模型:
User.findAll({ include: [{ all: true }]});
包括軟刪除的數據
如果要在結果中包含軟刪除的數據,請將include.paranoid
設置爲true
:
User.findAll({ include: [{ model: Tool, where: { name: { $like: '%ooth%' } }, paranoid: true // 查詢並加載軟刪除的數據 }] });
預加載關聯數據的排序
在1對多(one-to-many)的關係中:
Company.findAll({ include: [ Division ], order: [ [ Division, 'name' ] ] }); Company.findAll({ include: [ Division ], order: [ [ Division, 'name', 'DESC' ] ] }); Company.findAll({ include: [ { model: Division, as: 'Div' } ], order: [ [ { model: Division, as: 'Div' }, 'name' ] ] }); Company.findAll({ include: [ { model: Division, as: 'Div' } ], order: [ [ { model: Division, as: 'Div' }, 'name', 'DESC' ] ] }); Company.findAll({ include: [ { model: Division, include: [ Department ] } ], order: [ [ Division, Department, 'name' ] ] });
在多對多(many-to-many)的關係中同樣可以使用排序:
Company.findAll({ include: [ { model: Division, include: [ Department ] } ], order: [ [ Division, DepartmentDivision, 'name' ] ] });
嵌套預加載
可以在關聯模型中嵌套預加載關係模型:
User.findAll({ include: [ {model: Tool, as: 'Instruments', include: [ {model: Teacher, include: [ /* etc */]} ]} ] }).then(function(users) { console.log(JSON.stringify(users)) /* [{ "name": "John Doe", "id": 1, "createdAt": "2013-03-20T20:31:45.000Z", "updatedAt": "2013-03-20T20:31:45.000Z", "Instruments": [{ // 1:M and N:M association "name": "Toothpick", "id": 1, "createdAt": null, "updatedAt": null, "userId": 1, "Teacher": { // 1:1 association "name": "Jimi Hendrix" } }] }] */ })
這會生成一個外連接,但where
子句的關係模型會使用內連接並返回唯一一個子句:
User.findAll({ include: [{ model: Tool, as: 'Instruments', include: [{ model: Teacher, where: { school: "Woodstock Music School" }, required: false }] }] }).then(function(users) { /* ... */ })
include
同樣支持嵌套加載:
User.findAll({ include: [{ all: true, nested: true }]});
3. Model
類的API
Model
相當於數據庫中表,有時你也會看到它被稱爲“模型”、或簡單的被爲“工廠”。這個類不能顯式的(通過構造函數)創建實例,而是應該通過sequelize.define
方法來創建,對於已經創建可以通過sequelize.import
方法來導入。
3.1 removeAttribute()
- 移除屬性
removeAttribute([attribute])
從已定義的模型中移除屬性
參數
名稱 | 類型 | 說明 |
---|---|---|
[attribute] | String |
使用示例:
let User = sequelize.define('user', { firstName: Sequelize.STRING, lastName: Sequelize.STRING }); User.sync().then(function(result){ User.create({firstName:'xxxx', lastName:'xxxx'}) .then(function(result){ User.findOne({raw:true}) .then(function(result){ console.log(result); // { id: 1, firstName: 'xxxx', lastName: 'xxxx'} // 移'firstName'屬性 User.removeAttribute('firstName'); User.findOne({raw:true}) .then(function(result){ console.log(result); // // { id: 1, lastName: 'xxxx'} }) }) }) })
3.2 sync()
- 同步模型到數據庫
sync() -> Promise.
同步Model
結構到數據庫中,即:在數據庫中創建表。執行成功後,會在回調中返回模弄的實例(this
)。
與sequelize.sync
的不同
Model.sync()
只會同步當前模型到數據庫中,而sequelize.sync()
會同步sequelize
實例中定義所有模型。
let User = sequelize.define('user', { firstName: Sequelize.STRING, lastName: Sequelize.STRING }); let Role = sequelize.define('role', { roleName: Sequelize.STRING }); let UserRole = sequelize.define('userRole', { userId: Sequelize.INTEGER, roleId: Sequelize.STRING }); User.sync().then(function(result){ // 同步了'User'一個模型 }) sequelize.sync().then(function(result){ // 同步了'Role'、'UserRole'、'UserRole'三個模型 })
相關
3.3 drop()
- 刪除數據庫中的表
drop([options]) -> Promise
刪除Model
在數據庫中對應的表。
參數
名稱 | 類型 | 屬性 |
---|---|---|
[options] | Object | |
[options.cascade=false] | Boolean | 同時移除依賴於該表的對象,如視圖。僅 postgres適用 |
[options.logging=false] | Function | 一個函數用於打印查詢時的sql |
[options.benchmark=false] | Boolean | 在打印日誌時同時輸出執行SQL花費的時候(毫秒) |
3.4 schema()
- 指定schema
schema(schema, [options]) -> this
爲Model
指定schema
(數據庫)。在postgres中將會設置爲"schema"."tableName"
,而在mysql和sqlite中將會設置爲'schema.tablename'
參數
名稱 | 類型 | 屬性 |
---|---|---|
schema | String | schema名 |
[options] | Object | |
[options.schemaDelimiter='.'] | String | schema與表名的分隔符 |
[options.logging=false] | Function | 一個函數用於打印查詢時的sql |
[options.benchmark=false] | Boolean | 在打印日誌時同時輸出執行SQL花費的時候(毫秒) |
3.5 getTableName()
- 獲取表名
getTableName([options]) -> String|Object
獲取Model
在數據庫中的表名。在未指定schema
時會返回模型名,或返回一個包含tableName
、schema
和delimiter
屬性的對象。
參數
名稱 | 類型 | 屬性 |
---|---|---|
schema | String | schema名 |
[options] | Object | |
[options.logging=false] | Function | 一個函數用於打印查詢時的sql |
[options.benchmark=false] | Boolean | 在打印日誌時同時輸出執行SQL花費的時候(毫秒) |
3.6 addScope()
- 添加限制範圍
addScope(name, scope, [options])
爲模型添加一個新的限制範圍。在定義模型時如果未指定驗證,這一方法會非常有用。
如果指定的限制已經存在,默認會拋出異常,這時可以傳入override: true
選項來解決。
參數
名稱 | 類型 | 說明 |
---|---|---|
name | String | 限制範圍名。使用defaultScope 是,會替換默認的限制 |
scope | Object | Function | |
[options] | Object | |
[options.override=false] | Boolean |
3.7 scope()
- 應用限制範圍
scope(options*) -> Model
在應用在define
定義模型時創建的作用範圍。如,在定義模型時我們會像下面這樣創建作用範圍:
var Model = sequelize.define('model', attributes, { defaultScope: { where: { username: 'dan' }, limit: 12 }, scopes: { isALie: { where: { stuff: 'cake' } }, complexFunction: function(email, accessLevel) { return { where: { email: { $like: email }, accesss_level { $gte: accessLevel } } } } } })
定義默認的限制範圍後,默認限制會在每次查詢時起作用:
Model.findAll() // WHERE username = 'dan' Model.findAll({ where: { age: { gt: 12 } } }) // WHERE age > 12 AND username = 'dan'
我們可以通過scope()
像下面這樣應用限制範圍:
Model.scope({ method: ['complexFunction' '[email protected]', 42]}).findAll() // WHERE email like '[email protected]%' AND access_level >= 42
3.8 findAll()
- 查詢多條數據
findAll([options]) -> Promise.<Array.<Instance>>
查詢多個實例(多條數據)。
如,在查詢中使用AND
和=
:
Model.findAll({ where: { attr1: 42, attr2: 'cake' } }) // WHERE attr1 = 42 AND attr2 = 'cake'
在查詢中使用大於
、小於
等:
Model.findAll({ where: { attr1: { $gt: 50 }, attr2: { $lte: 45 }, attr3: { $in: [1,2,3] }, attr4: { $ne: 5 } } }) // WHERE attr1 > 50 AND attr2 <= 45 AND attr3 IN (1,2,3) AND attr4 != 5
在查詢中使用OR
:
Model.findAll({ where: { name: 'a project', $or: [ {id: [1, 2, 3]}, { $and: [ {id: {gt: 10}}, {id: {lt: 100}} ] } ] } }); //WHERE `Model`.`name` = 'a project' AND (`Model`.`id` IN (1, 2, 3) OR (`Model`.`id` > 10 AND `Model`.`id` < 100));
查詢成功後會返回包含多個實例(instance
)的數組。
別名:all
相關
參數
名稱 | 類型 | 說明 |
---|---|---|
[options] | Object | |
[options.where] | Object | 一個描述查詢限制範圍(WHERE 條件)的對象 |
[options.attributes] | Array.<String> | Object | 要查詢的屬性(字段)列表,或一個include 和 exclude 對象的鍵。要對屬性進行重命名,可以傳入一個包含兩個元素的數組-第一個表示屬性在數據庫中的名稱或(或一些類似 Sequelize.literal , Sequelize.fn 等的表達式),第二個屬性表示要在返回實例中使用的名稱 |
[options.attributes.include] | Array.<String> | 選擇所有模型屬性並添加一些附加值,用於聚合計算。如:{attributes:{ |
[options.attributes.exclude] | Array.<String> | 選擇模型中除少數屬性外的所有屬性,這主要出於安全目錄。 如:{ attributes: { exclude: ['password'] } } |
[options.paranoid=true] | Boolean | 爲true 時,只會未刪除的記錄會返回,否則會返回刪除和未刪除的全部記錄 |
[options.include] | Array.<Object | Model> | 一個用於左連接的連接列表, 支持 { include: [ Model1, Model2, ...]} 或 { include: [{ model: Model1, as: 'Alias' }]} 的形式如果你的連接要設置 as (如 X.hasMany(Y, { as: 'Z } , 你需要將要加載的 Y 的as屬性指定爲Z) |
[options.include[].model] | Model | 你想要加載的模型 |
[options.include[].as] | String | 別名關係,如果你想對要加載的模型起別名。 對於 hasOne / belongsTo , 這地應該使用單數形式名,而對於hasMany 則應該使用複數形式名 |
[options.include[] .association] | Association | 想要加載的關係(這可以用來替代提供的一個model/as對) |
[options.include[].where] | Object | 用於子模型的WHERE 分句。注意,這會對要加載的使用內連接,除非顯示指定required: false |
[options.include[].or=false] | Boolean | 是否將 ON 和 WHERE 分名與 OR綁定在一起而不是替換 AND |
[options.include[].on] | Object | 爲連接提供你的 ON 條件 |
[options.include[].attributes] | Array.<String> | 要從子模型中查詢的屬性列表 |
[options.include[].required] | Boolean | 如果爲true ,會轉換爲內連接。這意味着,只有匹配到子模型的父模型纔會被加載。include.where 設置後爲True,其它情況 false |
[options.include[].separate] | Boolean | 如果爲true ,運行一個單獨的查詢來獲取關聯的實例,僅支持hasMany 關係 |
[options.include[].limit] | Number | 限制連接的行數,僅在include.separate=true 時支持 |
[options.include[] .through.where] | Object | 爲 belongsToMany 關係,過濾連接的模型 |
[options.include[] .through.attributes] | Array | 在 belongsToMany 關係中,連接模型選擇的屬性列表 |
[options.include[].include] | Array.<Object | Model> | 進一步嵌套相關模型 |
[options.order] | String | Array | Sequelize.fn | 指定一個排序. 如果是字符串,那麼會進行編碼。 如果是數組,那麼可以依次提供多組 列名/排序函數 ,每一組包含兩個元素,第一個是排序字段名,第二個是排序方式,如: order: [['name', 'DESC']] 。這種情況下,列名會進行編碼而排序方向不會 |
[options.limit] | Number | |
[options.offset] | Number | |
[options.transaction] | Transaction | 在事務中執行查詢 |
[options.lock] | String | Object | 鎖定已選行. 可選項有: transaction.LOCK.UPDATE、 transaction.LOCK.SHARE, Postgres還支持: supports transaction.LOCK.KEY_SHARE、 transaction.LOCK.NO_KEY_UPDATE 和指定模型的連接鎖 詳見 transaction.LOCK |
[options.raw] | Boolean | 返回原始結果. 詳見 sequelize.query |
[options.logging=false] | Function | 一個用於打印執行SQL語句的函數 |
[options.having] | Object | |
[options .searchPath=DEFAULT] | String | 一個用於指定 schema 的 search_path 的可選項(僅 Postgres 適用) |
[options.benchmark=false] | Boolean | 打印執行SQL語句時,同時輸出執行時間(毫秒) |
3.9 findById()
- 通過Id查詢單條數據
findById(id, [options]) -> Promise.<Instance>
通過Id(主鍵)查詢單個實例(單條數據)。
參數
名稱 | 類型 | 說明 |
---|---|---|
id | Number | String | Buffer | 要查詢實例的主鍵 |
[options] | Object | |
[options.transaction] | Transaction | 在事務中執行查詢 |
[options .searchPath=DEFAULT] | String | 指定schema的 search_path (僅 Postgres) |
別名:findByPrimary
3.10 findOne()
- 通過單條數據
findById(id, [options]) -> Promise.<Instance>
查詢單個實例(單條數據)。這將會使用LIMIT 1
查詢條件,所以回調中總是返回單個實例。
參數
名稱 | 類型 | 說明 |
---|---|---|
[options] | Object | |
[options.transaction] | Transaction | 在事務中執行查詢 |
[options.searchPath=DEFAULT] | String | 指定schema的 search_path (僅 Postgres) |
3.11 aggregate()
- 聚合查詢
aggregate(field, aggregateFunction, [options]) -> Promise.<options.dataType|object>
在指定字段field
上運行聚合查詢。
參數
名稱 | 類型 | 說明 |
---|---|---|
field | String | 要運行聚合的字段。可以是字段名或* |
aggregateFunction | String | 聚合函數,如sum , max etc. |
[options] | Object | 查詢選項,可通過sequelize.query 查看所有選項 |
[options.where] | Object | 查詢屬性 |
[options.logging=false] | Function | 一個用於打印查詢時所執行sql的函數 |
[options.dataType] | DataType | String | 結果類型。如field 是模型中的字段,默認爲字段的類型,其它情況爲默認爲 float |
[options.distinct] | boolean | 爲字段使用DISTINCT 聚合查詢 |
[options.transaction] | Transaction | 在事務中運行查詢 |
[options.plain] | Boolean | 當爲true 時,第一個aggregateFunction 的返回值爲dataType 指定和返回,如果添加了額外的屬性,則由group 分句決定。設置plain 爲 false 時會返回所有返回行中的所有值 。默認爲 true |
[options.benchmark=false] | Boolean | 當打印SQL日誌時同時輸出查詢執行時間(毫秒) |
3.12 count()
- 統計查詢結果數
count([options]) -> Promise.<Integer>
統計符合查詢條件的結果總數。
如果提供了include
,將計算匹配關聯的數目
參數
名稱 | 類型 | 說明 |
---|---|---|
[options] | Object | |
[options.where] | Object | 查詢屬性(條件) |
[options.include] | Object | Include 選項 |
[options.distinct] | boolean | 在主鍵上使用 COUNT(DISTINCT(col)), Model.aggregate 要使用其它列 |
[options.attributes] | Object | 在 group 中聯合使用 |
[options.group] | Object | 創建複雜統計時,會返回所需要的多行 |
[options.transaction] | Transaction | 在事務中執行查詢Transaction to run query under |
[options.logging=false] | Function | 一個用於打印查詢時所執行sql的函數 |
[options .searchPath=DEFAULT] | String | 指定schema的 search_path (僅 Postgres) |
[options.benchmark=false] | Boolean | 當打印SQL日誌時同時輸出查詢執行時間(毫秒) |
3.13 findAndCount()
- 分頁查詢
findAndCount([findOptions]) -> Promise.<Object>
查詢由offset/limit
指定的所有匹配行,並返回查詢條件所匹配的總數量。
Model.findAndCountAll({ where: ..., limit: 12, offset: 12 }).then(function (result) { ... })
在上面查詢中,result
是一個包含以兩個屬性的對象:
{ rows: [], count: }
result.rows
是匹配的查詢行,result.count
是查詢條件匹配的總數量。
如果提供了include
,將計算匹配關聯的數目
User.findAndCountAll({ include: [ { model: Profile, required: true} ], limit 3 });
參數
名稱 | 類型 | 說明 |
---|---|---|
[findOptions] | Object | 參見 findAll |
別名:findAndCountAll
3.14 max()
- 查詢最大值
max(field, [options]) -> Promise.<Any>
查詢指定字段的最大值
參數
名稱 | 類型 | 說明 |
---|---|---|
field | String | |
[options] | Object | 參見 Object |
3.15 min()
- 查詢最大值
min(field, [options]) -> Promise.
查詢指定字段的最小值
參數
名稱 | 類型 | 說明 |
---|---|---|
field | String | |
[options] | Object | 參見 Object |
3.16 sum()
- 求和
sum(field, [options]) -> Promise.<Number>
對指定字段求和
參數
名稱 | 類型 | 說明 |
---|---|---|
field | String | |
[options] | Object | 參見 Object |
3.17 build()
- 創建新實例
build(values, [options]) -> Instance
創建一個新的模型實例,Values
參數爲新例指定的鍵值對對象
參數
名稱 | 類型 | 說明 |
---|---|---|
values | Object | |
[options] | Object | |
[options.raw=false] | Boolean | 設置爲true 時,值會忽略字段和虛擬設置器 |
[options.isNewRecord=true] | Boolean | |
[options.include] | Array | 用於構建prefetched/included 模型,參見 set |
3.18 create()
- 創建保存新實例
create(values, [options]) -> Promise.<Instance>
構建一個新的模型實例,並進行保存。與build()
方法不同的是,此方法除創建新實例外,還會將其保存到對應數據庫表中。
參數
名稱 | 類型 | 說明 |
---|---|---|
values | Object | |
[options] | Object | |
[options.raw=false] | Boolean | 設置爲true 時,值會忽略字段和虛擬設置器 |
[options.isNewRecord=true] | Boolean | |
[options.fields] | Array | 如果設置後,只有列表中區別的列纔會進行保存 |
[options.include] | Array | 用於構建prefetched/included 模型,參見 set |
[options.onDuplicate] | String | |
[options.transaction] | Transaction | 在事務中執行查詢 |
[options.logging=false] | Function | 一個用於打印查詢時所執行sql的函數 |
[options.searchPath=DEFAULT] | String | 指定schema的 search_path (僅 Postgres) |
[options.benchmark=false] | Boolean | 當打印SQL日誌時同時輸出查詢執行時間(毫秒) |
3.19 findOrInitialize()
- 查找或初始化
findOrInitialize -> Promise.<Instance, initialized>
查找一行記錄,如果不存在則創建(不保存)實例
參數
名稱 | 類型 | 說明 |
---|---|---|
options | Object | |
options.where | Object | 查詢屬性 |
[options.defaults] | Object | 用於創建新實例的默認值 |
[options.transaction] | Transaction | 在事務中執行查詢 |
[options.logging=false] | Function | 一個用於打印查詢時所執行sql的函數 |
[options.searchPath=DEFAULT] | String | 指定schema的 search_path (僅 Postgres) |
[options.benchmark=false] | Boolean | 當打印SQL日誌時同時輸出查詢執行時間(毫秒) |
別名:findOrBuild
3.20 findOrCreate()
- 查找或創建
findOrCreate(options) -> Promise.<Instance, created>
查找一行記錄,如果不存在則創建實例並保存到數據庫中
在這個方法中,如果options
對象中沒有傳入事務,那麼會在內部自動創建一個新的事務,以防止在創建完成之前有新匹配查詢進入。
參數
名稱 | 類型 | 說明 |
---|---|---|
options | Object | |
options.where | Object | 查詢屬性 |
[options.defaults] | Object | 用於創建新實例的默認值 |
[options.transaction] | Transaction | 在事務中執行查詢 |
3.21 findCreateFind()
- 查找或創建
findCreateFind(options) -> Promise.<Instance, created>
效率更高的findOrCreate
,不會在事務中執行。首先會嘗試進行查詢,如果爲空則嘗試創建,如果是唯一約束則嘗試再次查找。
參數
名稱 | 類型 | 說明 |
---|---|---|
options | Object | |
options.where | Object | 查詢屬性 |
[options.defaults] | Object | 用於創建新實例的默認值 |
[options.transaction] | Transaction | 在事務中執行查詢 |
3.22 upsert()
- 創建或更新
upsert(values, [options]) -> Promise.<created>
創建或更新一行。如果匹配到主鍵或唯一約束鍵時會進行更新。
執行詳細:
- MySQL - 做爲單條查詢執行
INSERT values ON DUPLICATE KEY UPDATE values
- PostgreSQL - 作爲一個臨時性的異常處理函數來實現:
INSERT EXCEPTION WHEN unique_constraint UPDATE
- SQLite - 做爲兩條查詢執行
INSERT; UPDATE
。這意味着,無論該行是否存在都會進行更新
參數
名稱 | 類型 | 說明 |
---|---|---|
values | Object | |
[options] | Object | |
[options.validate=true] | Boolean | 插入前進行驗證 |
[options.fields=Object.keys(this.attributes)] | Array | 要插入/更新字段。默認全部 |
[options.transaction] | Transaction | 在事務中執行查詢 |
別名:insertOrUpdate
3.23 bulkCreate()
- 創建多條記錄
bulkCreate(records, [options]) -> Promise.<Array.<Instance>>
批量創建並保存多個實例。
處理成功後,會在回調函數中返回一個包含多個實例的數組。
參數
名稱 | 類型 | 說明 |
---|---|---|
records | Array | 要創建實例的對象(鍵/值 對)列表 |
[options] | Object | |
[options.fields] | Array | 要插入的字段。默認全部 |
[options.validate=true] | Boolean | 插入每條記錄前進行驗證 |
[options.hooks=true] | Boolean | 在執行前/後創建鉤子 |
[options.individualHooks=false] | Boolean | 在執行前/後爲每個實例創建鉤子 |
[options.ignoreDuplicates=false] | Boolean | 忽略重複主鍵(Postgres不支持) |
[options.updateOnDuplicate] | Array | 如果行鍵已存在是否更新(mysql & mariadb支持). 默認爲更新 |
[options.transaction] | Transaction | 在事務中執行查詢 |
3.24 truncate()
- 截斷模型
truncate([options]) -> Promise
截斷模型的所有實例,這個方法是Model.destroy({ truncate: true })
便捷方法。
參數
名稱 | 類型 | 說明 |
---|---|---|
records | Array | 要創建實例的對象(鍵/值 對)列表 |
[options] | Object | |
[options.transaction] | Transaction | 在事務中執行查詢 |
[options.cascade=false] | Boolean | function | 僅適用於連接查詢時的TRUNCATE 操作,截斷所有外鍵匹配的表 |
3.25 destroy()
- 刪除記錄
destroy(options) -> Promise.<Integer>
刪除多個實例,或設置deletedAt的時間戳爲當前時間(當啓用paranoid
時)
執行成功後返回被刪除的行數
參數
名稱 | 類型 | 說明 |
---|---|---|
options | Object | |
[options.where] | Object | 篩選條件 |
[options.hooks=true] | Boolean | 在執行前/後創建鉤子 |
[options.individualHooks=false] | Boolean | 在執行前/後爲每個實例創建鉤子 |
[options.limit] | Number | 要刪除的行數 |
[options.force=false] | Boolean | 刪除而不是設置 deletedAt 爲當前時間戳 (僅啓用 paranoid 時適用) |
[options.truncate=false] | Boolean | 設置爲true 時,會使用TRUNCATE 代替DELETE FROM ,這時會忽略where 和limit 選項 |
[options.cascade=false] | Boolean | 僅適用於連接查詢時的TRUNCATE 操作,截斷所有外鍵匹配的表 |
[options.transaction] | Transaction | 在事務中執行查詢 |
3.26 restore()
- 恢復記錄
restore(options) -> Promise.<undefined>
恢復多個實例,當啓用paranoid
時
參數
名稱 | 類型 | 說明 |
---|---|---|
options | Object | |
[options.where] | Object | 篩選條件 |
[options.hooks=true] | Boolean | 在執行前/後創建鉤子 |
[options.individualHooks=false] | Boolean | 在執行前/後爲每個實例創建鉤子 |
[options.limit] | Number | 要恢復的行數 |
[options.transaction] | Transaction | 在事務中執行查詢 |
3.27 update()
- 更新記錄
update(values, options) -> Promise.<Array.<affectedCount, affectedRows>>
更新所匹配的多個實例。promise回調中會返回一個包含一個或兩個元素的數組,第一個元素始終表示受影響的行數,第二個元素表示實際影響的行(僅Postgreoptions.returning
爲true時受支持)
參數
名稱 | 類型 | 說明 |
---|---|---|
values | Object | |
options | Object | |
options.where | Object | 篩選條件 |
[options.fields] | Array | 要更新字段,默認爲全部 |
[options.validate=true] | Boolean | 更新每條記錄前進行驗證 |
[options.hooks=true] | Boolean | 在執行更新前/後創建鉤子 |
[options.individualHooks=false] | Boolean | 在執行更新前/後爲每個實例創建鉤子 |
[options.sideEffects=true] | Boolean | 是否更新任何虛擬設置 |
[options.returning=false] | Boolean | 返回受影響的行 (僅適用於 postgres) |
[options.limit] | Number | 要更新的行數 (僅適用於 mysql 和 mariadb) |
[options.transaction] | Transaction | 在事務中執行查詢 |
[options.silent=false] | Boolean | 如果爲true ,updatedAt字段將不會更新 |
3.28 describe()
- 查詢表信息
describe() -> Promise
運行一個表的描述查詢,返回結果中將包含屬性及其類型:
let User = sequelize.define('user', { firstName: Sequelize.STRING, lastName: Sequelize.STRING }); User.describe().then(function(result){ console.log(result); }) // 結果如下 { id: { type: 'INT(11)', allowNull: false, defaultValue: null, primaryKey: true }, firstName: { type: 'VARCHAR(255)', allowNull: true, defaultValue: null, primaryKey: false }, lastName: { type: 'VARCHAR(255)', allowNull: true, defaultValue: null, primaryKey: false } }