Sequelize 中文API文檔-5. 實例的使用、Instance類介紹

Instance類表示數據庫中的一行記錄,該類不能直接實例化,而應該由Model對象創建。Instance實例有兩種,由Model.build方法創建的非持久化實例,和由Model.create方法創建的持久化實例。應該注意,Instance翻譯後也叫做“實例”,但它在Sequelize 中是一個類,它的實例應該叫做“實例”類的實例。


  1. 實例的創建與使用
  2. 2. Instance類的API

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,結果中沒有自增屬性。而updatedestroy會返回受影響的行數。

批量創建操作:

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(/* ... */)

更多關於incrementincrement的使用請參考:


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,但它只保存傳遞給它確切值,使用它更新時更原子和更安全。

  • updates - {Object},見set
  • options - {Object},見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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章