Instance
類表示數據庫中的一行記錄,該類不能直接實例化,而應該由Model
對象創建。Instance
實例有兩種,由Model.build
方法創建的非持久化實例,和由Model.create
方法創建的持久化實例。應該注意,Instance
翻譯後也叫做“實例”,但它在Sequelize 中是一個類,它的實例應該叫做“實例”類的實例。
- 實例的創建與使用
- 2.
Instance
類的API- 2.1
isNewRecord
- 是否新記錄 - 2.2
Model()
- 創建實例的模型 - 2.3
sequelize()
- Sequelize實例 - 2.4
where()
- 實例的查詢條件 - 2.5
getDataValue()
- 獲取值 - 2.6
setDataValue()
- 設置值 - 2.7
get()
- 獲取值(單個或全部) - 2.8
set()
- 設置值 - 2.9
changed()
- 判斷是否修改 - 2.10
previous()
- 返回修改前的值 - 2.11
save()
- 保存實例到數據庫 - 2.12
reload()
- 重新加載數據 - 2.13
validate()
- 驗證屬性 - 2.14
update()
- 設置並保存 - 2.15
destroy()
- 刪除 - 2.16
restore()
- 數據恢復 - 2.17
increment()
- 字段值增加 - 2.18
decrement()
- 字段值減小 - 2.19
equals()
- 實例值是否相等 - 2.20
equalsOneOf()
- 實例值其中的一個相等 - 2.21
toJSON()
- 轉換成JSON
- 2.1
1. 實例的創建與使用
1.1 構建非持久化實例
爲了創建定義類的實例,需要像下面這樣做。使用build
方法會返回一個未保存的對象,你應該顯式的調用save
方法保存。
var project = Project.build({ title: '這是一個項目', description: '項目的描述,來自:itbilu.com' }) var task = Task.build({ title: 'specify the project idea', description: 'bla', dea
構建的實例會自動獲取我們定義的默認值:
// 先定義模型 var Task = sequelize.define('task', { title: Sequelize.STRING, rating: { type: Sequelize.STRING, defaultValue: 3 } }) // build 構建一個實例 var task = Task.build({title: 'very important task'}) task.title // ==> 'very important task' task.rating // ==> 3
要將構建非持久實例保存到數據庫中,需要使用use
方法:
project.save().then(function() { // 保存後的回調 }) task.save().catch(function(error) { // mhhh, wth! }) // 也可以鏈式的build構建實例,再you can also build, save and access the object with chaining: Task .build({ title: 'foo', description: 'bar', deadline: new Date() }) .save() .then(function(anotherTask) { // 現在可以通過anotherTask變量,訪問已保存的 task }).catch(function(error) { // Ooops, 錯誤處理 })
1.2 創建持久化實例
除了顯式的調用save
方法保存實例外,還可以create
方法創建並保存實例。
Task.create({ title: 'foo', description: 'bar', deadline: new Date() }).then(function(task) { // 現在可以通過 task 變量訪問新創建的 Task })
1.3 實例的更新/保存/持久化
修改實例的一些值,並保存到數據庫可以通過以下兩種方式實現:
// 方法 1 task.title = 'a very different title now' task.save().then(function() {}) // 方法 2 task.update({ title: 'a very different title now' }).then(function() {})
可樣可以設置哪些屬性需要保存,傳入一個包含字段名的數組即可。
task.title = 'foooo' task.description = 'baaaaaar' task.save({fields: ['title']}).then(function() { // 現在 title 是 'foooo' 但是 description 還是和以前一樣 }) // 同樣可以使用 update 方法進行保存: task.update({ title: 'foooo', description: 'baaaaaar'}, {fields: ['title']}).then(function() { // 現在 title 是 'foooo' 但是 description 還是和以前一樣 })
當調用save
但不做任何修改時,該方法不會做任何操作。
1.4 刪除持久化實例
創建對象並獲取對象引用後,可以通過destroy
方法將其從數據庫中刪除:
Task.create({ title: 'a task' }).then(function(task) { // 這樣刪除... return task.destroy(); }).then(function() { // 刪除完成 :) })
1.5 批量操作
除更新單個實例外,還可以創建、更新和刪除多個實例。批量操作的方法有:
Model.bulkCreate
Model.update
Model.destroy
當操作多個模型時,回調中不會返回DAO 實例。bulkCreate
會一個包含多個實例/DAO的數組,但不像create
,結果中沒有自增屬性。而update
和destroy
會返回受影響的行數。
批量創建操作:
User.bulkCreate([ { username: 'barfooz', isAdmin: true }, { username: 'foo', isAdmin: true }, { username: 'bar', isAdmin: false } ]).then(function() { // Notice: There are no arguments here, as of right now you'll have to... return User.findAll(); }).then(function(users) { console.log(users) // ... in order to get the array of user objects })
更新多條數據:
Task.bulkCreate([ {subject: 'programming', status: 'executing'}, {subject: 'reading', status: 'executing'}, {subject: 'programming', status: 'finished'} ]).then(function() { return Task.update( { status: 'inactive' }, /* set attributes' value */, { where: { subject: 'programming' }} /* where criteria */ ); }).spread(function(affectedCount, affectedRows) { // .update 會返會一個包含兩個值的數組,使用 .spread展開 // 注意,只有支持 returning: true屬性的數據庫纔會返回 affectedRows // affectedCount 是 2 return Task.findAll(); }).then(function(tasks) { console.log(tasks) // subject爲 'programming' 的對象的 status屬性會更新爲 'inactive' })
刪除多條數據:
Task.bulkCreate([ {subject: 'programming', status: 'executing'}, {subject: 'reading', status: 'executing'}, {subject: 'programming', status: 'finished'} ]).then(function() { return Task.destroy({ where: { subject: 'programming' }, truncate: true /* 這會對錶使用truncate(截斷)操作 */ }); }).then(function(affectedRows) { // affectedRows 是2 2 return Task.findAll(); }).then(function(tasks) { console.log(tasks) // 沒有 programming, 只有 reading :( })
如果你是從用戶輸入接收值,那可想要設置要插入的值。bulkCreate()
接受第二個參數對象,你可以在其中傳入一個fields
(數組)參數,以表示哪些字段需要插入。
User.bulkCreate([ { username: 'foo' }, { username: 'bar', admin: true} ], { fields: ['username'] }).then(function() { // nope bar, you can't be admin! })
bulkCreate
是一種快速的插入數據的方式,但在插入多行數據時,我們又不希望犧牲模型驗證,這時可以通過validate
參數告訴Sequelize只有通過篩選的數據才能插入數據庫。
var Tasks = sequelize.define('task', { name: { type: Sequelize.STRING, validate: { notNull: { args: true, msg: 'name cannot be null' } } }, code: { type: Sequelize.STRING, validate: { len: [3, 10] } } }) Tasks.bulkCreate([ {name: 'foo', code: '123'}, {code: '1234'}, {name: 'bar', code: '1'} ], { validate: true }).catch(function(errors) { /* console.log(errors) would look like: [ { record: ... errors: { name: 'SequelizeValidationError', message: 'Validation error', errors: [Object] } }, { record: ... errors: { name: 'SequelizeValidationError', message: 'Validation error', errors: [Object] } } ] */ })
1.6 實例值
當我們打印實例時,會看到很多額外的值。爲了隱藏這些東西,可以使用get
-屬性,並使用plain = true
選項來返回實例值。
Person.create({ name: 'Rambow', firstname: 'John' }).then(function(john) { console.log(john.get({ plain: true })) }) // result: // { name: 'Rambow', // firstname: 'John', // id: 1, // createdAt: Tue, 01 May 2012 19:12:16 GMT, // updatedAt: Tue, 01 May 2012 19:12:16 GMT // }
1.7 實例的重新加載
實例中有一個reload
方法,該方法會同步數據中的當前的數據,並使用剛加載的數據對模型屬性進行重寫。
Person.findOne({ where: { name: 'john' } }).then(function(person) { person.name = 'jane' console.log(person.name) // 'jane' person.reload().then(function() { console.log(person.name) // 'john' }) })
1.8 實例字段值的增大
increment
方法,可以爲實例屬性(字段)增加一個確定義的字面值,該方法直接單個或多個字段屬性值的增加。
爲一個屬性增加值:
User.findById(1).then(function(user) { return user.increment('my-integer-field', {by: 2}) }).then(/* ... */)
爲多個屬性增加值:
User.findById(1).then(function(user) { return user.increment([ 'my-integer-field', 'my-very-other-field' ], {by: 2}) }).then(/* ... */)
也可以使用對象的形式爲多個屬性增加值:
User.findById(1).then(function(user) { return user.increment({ 'my-integer-field': 2, 'my-very-other-field': 3 }) }).then(/* ... */)
1.9 實例字段值的減小
我們可以向increment
方法傳入一個負數來減小字段值。相對應的,還有一個decrement
方法,該方法用於減小字段值:
爲一個屬性減小值:
User.findById(1).then(function(user) { return user.decrement('my-integer-field', {by: 2}) }).then(/* ... */)
爲多個屬性減小值:
User.findById(1).then(function(user) { return user.decrement([ 'my-integer-field', 'my-very-other-field' ], {by: 2}) }).then(/* ... */)
也可以使用對象的形式爲多個屬性減小值:
User.findById(1).then(function(user) { return user.decrement({ 'my-integer-field': 2, 'my-very-other-field': 3 }) }).then(/* ... */)
更多關於increment
、increment
的使用請參考:
2. Instance
類的API
Instance
類表示一個實例,表示數據庫中的一行。它不能通過構造函數實例化,而應該通過Model.find*或Model.create等方法創建。
實例中包含一個dataValues
屬性,其中存儲了實例實際所要操作的值。dataValues
中的值可以通過以下幾種方式訪問:
instance.field // 等價於 instance.get('field') // 等價於 instance.getDataValue('field')
如果定義了訪問器(getter)/設置器(setter),字段值從其中訪問而不是從dataValues
。一般會直接訪問或使用get
來訪問屬性值,而getDataValue
只用於自定義的訪問器。
相關
2.1 isNewRecord
- 是否新記錄
instance.isNewRecord -> Boolean
當實例是未保存到數據庫的非持久化實例時,返回true
2.2 Model()
- 創建實例的模型
instance.Model() -> Model
返回創建實例的Model
。
相關
2.3 sequelize()
- Sequelize實例
instance.sequelize() -> Sequelize
返回Sequelize實例的引用
相關
2.4 where()
- 實例的查詢條件
instance.where() -> Object
獲取當前實例的查詢條件,相當於option.where
2.5 getDataValue()
- 獲取值
instance.getDataValue(key) -> any
獲取底層數據值。
key
- {String},表示要獲取值的字段名
2.6 setDataValue()
- 設置值
instance.setDataValue(key, value)
設置底層數據值。
key
- {String},表示要設置值的字段名value
- {any},表示要設置的值
2.7 get()
- 獲取值(單個或全部)
instance.get([key], [options]) -> Object|any
不提供key
時,返回全部實例值。同樣適用於虛擬訪問器。
提供key
時,返回字段值或返回虛擬訪問器的值。
[key]
- {String},表示要訪問值的字段名[options]
- {Object}[options.plain=false]
- {Boolean},設置爲true時,返回簡單對象
2.8 set()
- 設置值
instance.set(key, value, [options])
set
用於更新實例值。set
更新的值會保存在底層的dataValues
對象中,如果爲所設置的key
設置了自定義設置器,那麼設置器被調用。如果要繞過這些設置器,可以在選項中設置raw: true
選項。
當通過一對象進行設置時,它會是一個循環對象,會爲其中的每個key/value
分別調用此方法。當設置raw
時,底層的dataValues
會被直接設置或擴展。
當值被修改後,修改值會被存儲在的previous
中,並會設置一個changed
標識。
Set
同樣可以用於構建關聯實例。當設置時,應該確認屬性鍵能夠匹配到關係實例的別名,並確認這些選項已設置關聯。
在JSON/JSONB屬性中,如果使用.
分隔的字段,那麼設置嵌套對象的值。
key
- {String | Object},表示要設置值的字段value
- {any},表示要設置的值[options]
- {Object}[options.raw=false]
- {Boolean},虛擬設置器會被忽略[options.reset=false]
- {Boolean},清除之前的設置數據
別名:setAttributes
2.9 changed()
- 判斷是否修改
instance.changed([key]) -> Boolean|Array
判斷字段或實例是否修改過,即判斷dataValues
中的值是否與_previousDataValues
中的值是否相同。
當不傳入參數時,會返回一個包含已修改字段的數組。當傳入參數時,返回一個表示該字段是否修改的布爾值。
2.10 previous()
- 返回修改前的值
instance.previous([key]) -> any|Array.<any>
返回實例修改前的值,即_previousDataValues
屬性中值。如果不傳入參數,則返回所有已修改的值。
2.11 save()
- 保存實例到數據庫
instance.save([options]) -> Promise.<this|Errors.ValidationError<
較驗數據,通過後持久化到數據庫中。這個方法僅會保存修改過的數據,如果未發生修改那麼不會進行任何操作。
操作成功會回調修改結果,驗證失敗則返回一個Sequelize.ValidationError
對象。
[options]
- {Object}[options.fields]
- {Array.<string>},可選的表示數據庫中字段值,提供後僅會驗證和保存其中的字段[[options.silent=false]]
- {Boolean},設置爲 true 時,updatedAt在更新時不會發生變化[options.validate=true]
- {Boolean},保存前時否驗證[options.logging=false]
- {Function},一個用於打印執行SQL的函數[options.transaction=false]
- {Transaction}[options.searchPath=DEFAULT]
- {String},指定schema的 search_path (僅 Postgres)
2.12 reload()
- 重新加載數據
instance.reload([options]) -> Promise.<this>
用數據庫中的數據當前實例。這不同於find(Instance.id)
,因爲它會創建並返回一個新實例。而該方法是用新數據刷新當前實例。
[options]
- {Object}[options.logging=false]
- {Function},一個用於打印執行SQL的函數
2.13 validate()
- 驗證屬性
instance.validate([options]) -> Promise.<Errors.ValidationError|undefined>
根據模型定義的驗證規則驗證模型屬性。驗證成功時返回null
,否則返回一個錯誤對象。
[options]
- {Object}[options.skip]
- {String|Array},包含一個要跳過的驗證字段的字符串或數組
2.14 update()
- 設置並保存
instance.update(updates, options) -> Promise.<this>
相當於調用set
方法後再調用save
,但它只保存傳遞給它確切值,使用它更新時更原子和更安全。
別名:updateAttributes
2.15 destroy()
- 刪除
instance.destroy([options={}]) -> Promise.<undefined>
刪除實例在數據庫中對應的行。設置爲軟刪除(paranoid
)時,數據行並不會真實刪除,而是將deletedAt
列更新爲當前時間。
[options]
- {Object}[options.force=false]
- {Boolean},強制刪除。設置爲 true時,軟刪除的模型也會強制刪除[options.logging=false]
- {Function},一個用於打印執行SQL的函數[options.transaction]
- {Transaction}[options.searchPath=DEFAULT]
- {String},指定schema的 search_path (僅 Postgres)
2.16 restore()
- 數據恢復
instance.restore([options={}]) -> Promise.<undefined>
恢復實例數據,僅適用於軟刪除(paranoid
)模型
[options]
- {Object}[options.logging=false]
- {Function},一個用於打印執行SQL的函數[options.transaction]
- {Transaction}
2.17 increment()
- 字段值增加
instance.increment(fields, [options]) -> Promise<this>
爲一個或多個字段增加值。這一操作在數據庫中完成,也就是說它並不使用實例的存儲值。其增加值使用如下語句完成:
SET column = column + X
增加後,要獲取正確的實例值應該使用reload()
方法重新加載數據。
fields
- {String | Array | Object},要增加值的字段[options]
- {Object}[options.by=1]
- {Integer},要增加的數字值[options.logging=false]
- {Function},一個用於打印執行SQL的函數[options.transaction]
- {Transaction}[options.searchPath=DEFAULT]
- {String},指定schema的 search_path (僅 Postgres)
instance.increment('number') // 增加 1 instance.increment(['number', 'count'], { by: 2 }) // 'number' 和 'count'兩個字段增加 2 instance.increment({ answer: 42, tries: 1}, { by: 2 }) // 'answer'字段增加 42, 'tries' 字段增加 1,'by' 參數將忽略,因爲每一列都有自己的值
2.18 decrement()
- 字段值減小
instance.decrement(fields, [options]) -> Promise<this>
爲一個或多個字段減小值。這一操作在數據庫中完成,也就是說它並不使用實例的存儲值。其增加值使用如下語句完成:
SET column = column - X
增加後,要獲取正確的實例值應該使用reload()
方法重新加載數據。
fields
- {String | Array | Object},要減小值的字段[options]
- {Object}[options.by=1]
- {Integer},要減小的數字值[options.logging=false]
- {Function},一個用於打印執行SQL的函數[options.transaction]
- {Transaction}[options.searchPath=DEFAULT]
- {String},指定schema的 search_path (僅 Postgres)
instance.decrement('number') // 減小 1 instance.decrement(['number', 'count'], { by: 2 }) // 'number' 和 'count'兩個字段減小 2 instance.decrement({ answer: 42, tries: 1}, { by: 2 }) // 'answer'字段減小 42, 'tries' 字段減小 1, 'by' 參數將忽略,因爲每一列都有自己的值
2.19 equals()
- 實例值是否相等
instance.equals(other) -> Boolean
檢查當前實例是否與other
實例的值相等
2.20 equalsOneOf()
- 實例值其中的一個相等
instance.equalsOneOf(others) -> Boolean
檢查當前實例是否與others
數組中的任意一個實例的值相等
2.21 toJSON()
- 轉換成JSON
instance.toJSON() -> object