一文搞懂Sequelize模型定義

要定義模型和表之間的映射,請(qǐng)使用 define 方法. 每列必須具有數(shù)據(jù)類型,請(qǐng)參閱 datatypes 的更多信息.

class Project extends Model {}
Project.init({
  title: Sequelize.STRING,
  description: Sequelize.TEXT
}, { sequelize, modelName: 'project' });

class Task extends Model {}
Task.init({
  title: Sequelize.STRING,
  description: Sequelize.TEXT,
  deadline: Sequelize.DATE
}, { sequelize, modelName: 'task' })

除了datatypes,你可以在每列上設(shè)置很多參數(shù).

class Foo extends Model {}
Foo.init({
 // 如果未賦值,則自動(dòng)設(shè)置值為 TRUE
 flag: { type: Sequelize.BOOLEAN, allowNull: false, defaultValue: true},

 // 設(shè)置默認(rèn)時(shí)間為當(dāng)前時(shí)間
 myDate: { type: Sequelize.DATE, defaultValue: Sequelize.NOW },

 // 將allowNull設(shè)置為false會(huì)將NOT NULL添加到列中,
 // 這意味著當(dāng)列為空時(shí)執(zhí)行查詢時(shí)將從DB拋出錯(cuò)誤. 
 // 如果要在查詢DB之前檢查值不為空,請(qǐng)查看下面的驗(yàn)證部分.
 title: { type: Sequelize.STRING, allowNull: false},

 // 創(chuàng)建具有相同值的兩個(gè)對(duì)象將拋出一個(gè)錯(cuò)誤. 唯一屬性可以是布爾值或字符串.
 // 如果為多個(gè)列提供相同的字符串,則它們將形成復(fù)合唯一鍵.
 uniqueOne: { type: Sequelize.STRING,  unique: 'compositeIndex'},
 uniqueTwo: { type: Sequelize.INTEGER, unique: 'compositeIndex'},

 // unique屬性用來創(chuàng)建一個(gè)唯一約束.
 someUnique: {type: Sequelize.STRING, unique: true},

 // 這與在模型選項(xiàng)中創(chuàng)建索引完全相同.
 {someUnique: {type: Sequelize.STRING}},
 {indexes: [{unique: true, fields: ['someUnique']}]},

 // primaryKey用于定義主鍵.
 identifier: { type: Sequelize.STRING, primaryKey: true},

 // autoIncrement可用于創(chuàng)建自增的整數(shù)列
 incrementMe: { type: Sequelize.INTEGER, autoIncrement: true },

 // 你可以通過'field'屬性指定自定義列名稱:
 fieldWithUnderscores: { type: Sequelize.STRING, field: 'field_with_underscores' },

 // 這可以創(chuàng)建一個(gè)外鍵:
 bar_id: {
   type: Sequelize.INTEGER,

   references: {
     // 這是引用另一個(gè)模型
     model: Bar,

     // 這是引用模型的列名稱
     key: 'id',

     // 這聲明什么時(shí)候檢查外鍵約束. 僅限PostgreSQL.
     deferrable: Sequelize.Deferrable.INITIALLY_IMMEDIATE
   }
 },

 // 僅可以為 MySQL,PostgreSQL 和 MSSQL 的列添加注釋
 commentMe: {
   type: Sequelize.INTEGER,

   comment: '這是一個(gè)包含注釋的列名'
 }
}, {
  sequelize,
  modelName: 'foo'
});

注釋選項(xiàng)也可以在表上使用, 查看 model configuration.

時(shí)間戳

默認(rèn)情況下,Sequelize 會(huì)將 createdAtupdatedAt 屬性添加到模型中,以便你能夠知道數(shù)據(jù)庫條目何時(shí)進(jìn)入數(shù)據(jù)庫以及何時(shí)被更新.

請(qǐng)注意,如果你使用 Sequelize 遷移,則需要將 createdAtupdatedAt 字段添加到遷移定義中:

module.exports = {
  up(queryInterface, Sequelize) {
    return queryInterface.createTable('my-table', {
      id: {
        type: Sequelize.INTEGER,
        primaryKey: true,
        autoIncrement: true,
      },

      // 時(shí)間戳
      createdAt: Sequelize.DATE,
      updatedAt: Sequelize.DATE,
    })
  },
  down(queryInterface, Sequelize) {
    return queryInterface.dropTable('my-table');
  },
}

如果你不想在模型上使用時(shí)間戳,只需要一些時(shí)間戳記,或者你正在使用現(xiàn)有的數(shù)據(jù)庫,其中列被命名為別的東西,直接跳轉(zhuǎn)到 configuration 以查看如何執(zhí)行此操作.

可延遲

當(dāng)你在 PostgreSQL 中指定外鍵列的參數(shù)來聲明成一個(gè)可延遲類型. 可用的選項(xiàng)如下:

// 將所有外鍵約束檢查推遲到事務(wù)結(jié)束時(shí).
Sequelize.Deferrable.INITIALLY_DEFERRED

// 立即檢查外鍵約束.
Sequelize.Deferrable.INITIALLY_IMMEDIATE

// 不要推遲檢查.
Sequelize.Deferrable.NOT

最后一個(gè)參數(shù)是 PostgreSQL 的默認(rèn)值,不允許你在事務(wù)中動(dòng)態(tài)的更改規(guī)則. 查看 事務(wù) 章節(jié)獲取補(bǔ)充信息.

Getters & setters

可以在模型上定義'對(duì)象屬性'getter 和 setter 函數(shù),這些可以用于映射到數(shù)據(jù)庫字段的 “保護(hù)” 屬性,也可以用于定義 “偽” 屬性.

Getters 和 Setters 可以通過兩種方式定義 (你可以混合使用這兩種方式):

  • 作為屬性定義的一部分
  • 作為模型參數(shù)的一部分

注意: 如果在兩個(gè)地方定義了 getter 或 setter,那么在相關(guān)屬性定義中找到的函數(shù)始終是優(yōu)先的.

定義為屬性定義的一部分

class Employee extends Model {}
Employee.init({
  name: {
    type: Sequelize.STRING,
    allowNull: false,
    get() {
      const title = this.getDataValue('title');
      // 'this' 允許你訪問實(shí)例的屬性
      return this.getDataValue('name') + ' (' + title + ')';
    },
  },
  title: {
    type: Sequelize.STRING,
    allowNull: false,
    set(val) {
      this.setDataValue('title', val.toUpperCase());
    }
  }
}, { sequelize, modelName: 'employee' });

Employee
  .create({ name: 'John Doe', title: 'senior engineer' })
  .then(employee => {
    console.log(employee.get('name')); // John Doe (SENIOR ENGINEER)
    console.log(employee.get('title')); // SENIOR ENGINEER
  })

定義為模型參數(shù)的一部分

以下是在模型參數(shù)中定義 getter 和 setter 的示例.

fullName getter,是一個(gè)說明如何在模型上定義偽屬性的例子 - 這些屬性實(shí)際上不是數(shù)據(jù)庫模式的一部分. 事實(shí)上,偽屬性可以通過兩種方式定義:使用模型 getter,或者使用虛擬數(shù)據(jù)類型的列. 虛擬數(shù)據(jù)類型可以有驗(yàn)證,而虛擬屬性的 getter 則不能.

請(qǐng)注意,fullName getter 函數(shù)中引用的this.firstnamethis.lastname將觸發(fā)對(duì)相應(yīng) getter 函數(shù)的調(diào)用. 如果你不想這樣,可以使用getDataValue()方法來訪問原始值 (見下文).

class Foo extends Model {
  get fullName() {
    return this.firstname + ' ' + this.lastname;
  }

  set fullName(value) {
    const names = value.split(' ');
    this.setDataValue('firstname', names.slice(0, -1).join(' '));
    this.setDataValue('lastname', names.slice(-1).join(' '));
  }
}
Foo.init({
  firstname: Sequelize.STRING,
  lastname: Sequelize.STRING
}, {
  sequelize,
  modelName: 'foo'
});

// 或使用 `sequelize.define`
sequelize.define('Foo', {
  firstname: Sequelize.STRING,
  lastname: Sequelize.STRING
}, {
  getterMethods: {
    fullName() {
      return this.firstname + ' ' + this.lastname;
    }
  },

  setterMethods: {
    fullName(value) {
      const names = value.split(' ');

      this.setDataValue('firstname', names.slice(0, -1).join(' '));
      this.setDataValue('lastname', names.slice(-1).join(' '));
    }
  }
});

用于 getter 和 setter 定義內(nèi)部的 Helper 方法

  • 檢索底層屬性值 - 總是使用 this.getDataValue()
/* 一個(gè)用于 'title' 屬性的 getter */
get() {
  return this.getDataValue('title')
}
  • 設(shè)置基礎(chǔ)屬性值 - 總是使用 this.setDataValue()
/* 一個(gè)用于 'title' 屬性的 setter */
set(title) {
  this.setDataValue('title', title.toString().toLowerCase());
}

注意: 堅(jiān)持使用 setDataValue()getDataValue() 函數(shù) (而不是直接訪問底層的 “數(shù)據(jù)值” 屬性) 是非常重要的 - 這樣做可以保護(hù)你的定制 getter 和 setter 不受底層模型實(shí)現(xiàn)的變化.

驗(yàn)證

模型驗(yàn)證允許你為模型的每個(gè)屬性指定格式/內(nèi)容/繼承驗(yàn)證.

驗(yàn)證會(huì)自動(dòng)運(yùn)行在 create , updatesave 上. 你也可以調(diào)用 validate() 手動(dòng)驗(yàn)證一個(gè)實(shí)例.

屬性驗(yàn)證器

你可以自定義驗(yàn)證器或使用由validator.js實(shí)現(xiàn)的幾個(gè)內(nèi)置驗(yàn)證器,如下所示.

class ValidateMe extends Model {}
ValidateMe.init({
  bar: {
    type: Sequelize.STRING,
    validate: {
      is: ["^[a-z]+$",'i'],     // 只允許字母
      is: /^[a-z]+$/i,          // 與上一個(gè)示例相同,使用了真正的正則表達(dá)式
      not: ["[a-z]",'i'],       // 不允許字母
      isEmail: true,            // 檢查郵件格式 (foo@bar.com)
      isUrl: true,              // 檢查連接格式 (http://foo.com)
      isIP: true,               // 檢查 IPv4 (129.89.23.1) 或 IPv6 格式
      isIPv4: true,             // 檢查 IPv4 (129.89.23.1) 格式
      isIPv6: true,             // 檢查 IPv6 格式
      isAlpha: true,            // 只允許字母
      isAlphanumeric: true,     // 只允許使用字母數(shù)字
      isNumeric: true,          // 只允許數(shù)字
      isInt: true,              // 檢查是否為有效整數(shù)
      isFloat: true,            // 檢查是否為有效浮點(diǎn)數(shù)
      isDecimal: true,          // 檢查是否為任意數(shù)字
      isLowercase: true,        // 檢查是否為小寫
      isUppercase: true,        // 檢查是否為大寫
      notNull: true,            // 不允許為空
      isNull: true,             // 只允許為空
      notEmpty: true,           // 不允許空字符串
      equals: 'specific value', // 只允許一個(gè)特定值
      contains: 'foo',          // 檢查是否包含特定的子字符串
      notIn: [['foo', 'bar']],  // 檢查是否值不是其中之一
      isIn: [['foo', 'bar']],   // 檢查是否值是其中之一
      notContains: 'bar',       // 不允許包含特定的子字符串
      len: [2,10],              // 只允許長度在2到10之間的值
      isUUID: 4,                // 只允許uuids
      isDate: true,             // 只允許日期字符串
      isAfter: "2011-11-05",    // 只允許在特定日期之后的日期字符串
      isBefore: "2011-11-05",   // 只允許在特定日期之前的日期字符串
      max: 23,                  // 只允許值 <= 23
      min: 23,                  // 只允許值 >= 23
      isCreditCard: true,       // 檢查有效的信用卡號(hào)碼

      // 自定義驗(yàn)證器的示例:
      isEven(value) {
        if (parseInt(value) % 2 !== 0) {
          throw new Error('Only even values are allowed!');
        }
      }
      isGreaterThanOtherField(value) {
        if (parseInt(value) <= parseInt(this.otherField)) {
          throw new Error('Bar must be greater than otherField.');
        }
      }
    }
  }
}, { sequelize });

請(qǐng)注意,如果需要將多個(gè)參數(shù)傳遞給內(nèi)置的驗(yàn)證函數(shù),則要傳遞的參數(shù)必須位于數(shù)組中. 但是,如果要傳遞單個(gè)數(shù)組參數(shù),例如isIn的可接受字符串?dāng)?shù)組,則將被解釋為多個(gè)字符串參數(shù),而不是一個(gè)數(shù)組參數(shù). 要解決這個(gè)問題,傳遞一個(gè)單一長度的參數(shù)數(shù)組,比如[['one','two']].

要使用自定義錯(cuò)誤消息而不是 validator.js 提供的錯(cuò)誤消息,請(qǐng)使用對(duì)象而不是純值或參數(shù)數(shù)組,例如不需要參數(shù)的驗(yàn)證器可以被給定自定義消息:

isInt: {
  msg: "Must be an integer number of pennies"
}

或者如果還需要傳遞參數(shù),請(qǐng)?zhí)砑右粋€(gè) args 屬性:

isIn: {
  args: [['en', 'zh']],
  msg: "Must be English or Chinese"
}

當(dāng)使用自定義驗(yàn)證器函數(shù)時(shí),錯(cuò)誤消息將是拋出的 Error 對(duì)象所持有的任何消息.

有關(guān)內(nèi)置驗(yàn)證方法的更多詳細(xì)信息,請(qǐng)參閱 validator.js project .

**提示: **你還可以為日志記錄部分定義自定義函數(shù). 只是傳遞一個(gè)方法. 第一個(gè)參數(shù)將是記錄的字符串.

屬性驗(yàn)證器 與 allowNull

如果模型的特定字段設(shè)置為不允許 null(使用allowNull:false) 并且該值已設(shè)置為 null,則將跳過所有驗(yàn)證器并拋出 ValidationError.

另一方面,如果將其設(shè)置為允許 null(使用 allowNull:true) 并且該值已設(shè)置為 null,則只會(huì)跳過內(nèi)置驗(yàn)證器,而自定義驗(yàn)證器仍將運(yùn)行.

例如,這意味著你可以使用一個(gè)字符串字段來驗(yàn)證其長度在 5 到 10 個(gè)字符之間,但也允許 null(因?yàn)楫?dāng)值為 null 時(shí),將自動(dòng)跳過長度驗(yàn)證器):

class User extends Model {}
User.init({
  username: {
    type: Sequelize.STRING,
    allowNull: true,
    validate: {
      len: [5, 10]
    }
  }
}, { sequelize });

你還可以使用自定義驗(yàn)證器有條件地允許 null 值,因?yàn)樗粫?huì)被跳過:

class User extends Model {}
User.init({
  age: Sequelize.INTEGER,
  name: {
    type: Sequelize.STRING,
    allowNull: true,
    validate: {
      customValidator(value) {
        if (value === null && this.age !== 10) {
          throw new Error("name can't be null unless age is 10");
        }
      })
    }
  }
}, { sequelize });

你可以通過設(shè)置 notNull 驗(yàn)證器來自定義 allowNull 錯(cuò)誤消息:

class User extends Model {}
User.init({
  name: {
    type: Sequelize.STRING,
    allowNull: false,
    validate: {
      notNull: {
        msg: 'Please enter your name'
      }
    }
  }
}, { sequelize });

模型范圍驗(yàn)證

驗(yàn)證器也可以在特定字段驗(yàn)證器之后用來定義檢查模型.例如,你可以確保緯度經(jīng)度都不設(shè)置,或者兩者都設(shè)置,如果設(shè)置了一個(gè)而另一個(gè)未設(shè)置則驗(yàn)證失敗.

模型驗(yàn)證器方法與模型對(duì)象的上下文一起調(diào)用,如果它們拋出錯(cuò)誤,則認(rèn)為失敗,否則通過. 這與自定義字段特定的驗(yàn)證器一樣.

所收集的任何錯(cuò)誤消息都將與驗(yàn)證結(jié)果對(duì)象一起放在字段驗(yàn)證錯(cuò)誤中,這個(gè)錯(cuò)誤使用在validate參數(shù)對(duì)象中以失敗的驗(yàn)證方法的鍵來命名.即便在任何一個(gè)時(shí)刻,每個(gè)模型驗(yàn)證方法只能有一個(gè)錯(cuò)誤消息,它會(huì)在數(shù)組中顯示為單個(gè)字符串錯(cuò)誤,以最大化與字段錯(cuò)誤的一致性.

一個(gè)例子:

class Pub extends Model {}
Pub.init({
  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() {
      if ((this.latitude === null) !== (this.longitude === null)) {
        throw new Error('Require either both latitude and longitude or neither')
      }
    }
  },
  sequelize,
})

在這種簡(jiǎn)單情況下,如果給定緯度或經(jīng)度,而不是同時(shí)包含兩者,則驗(yàn)證失敗. 如果我們嘗試構(gòu)建一個(gè)超范圍的緯度和經(jīng)度,那么raging_bullock_arms.validate()可能會(huì)返回

{
  'latitude': ['Invalid number: latitude'],
  'bothCoordsOrNone': ['Require either both latitude and longitude or neither']
}

這樣的驗(yàn)證也可以通過在單個(gè)屬性上定義的自定義驗(yàn)證器 (例如latitude屬性,通過檢查(value === null) !== (this.longitude === null)) 來完成, 但模型范圍的驗(yàn)證方法更清晰.

配置

你還可以修改 Sequelize 處理列名稱的方式:

class Bar extends Model {}
Bar.init({ /* bla */ }, {
  // 模型的名稱. 該模型將以此名稱存儲(chǔ)在`sequelize.models`中.
  // 在這種情況下,默認(rèn)為類名,即Bar. 
  // 這將控制自動(dòng)生成的foreignKey和關(guān)聯(lián)命名的名稱
  modelName: 'bar',
  // 不添加時(shí)間戳屬性 (updatedAt, createdAt)
  timestamps: false,

  // 不刪除數(shù)據(jù)庫條目,但將新添加的屬性deletedAt設(shè)置為當(dāng)前日期(刪除完成時(shí)). 
  // paranoid 只有在啟用時(shí)間戳?xí)r才能工作
  paranoid: true,

  // 將自動(dòng)設(shè)置所有屬性的字段參數(shù)為下劃線命名方式.
  // 不會(huì)覆蓋已經(jīng)定義的字段選項(xiàng)
  underscored: true,

  // 禁用修改表名; 默認(rèn)情況下,sequelize將自動(dòng)將所有傳遞的模型名稱(define的第一個(gè)參數(shù))轉(zhuǎn)換為復(fù)數(shù). 如果你不想這樣,請(qǐng)?jiān)O(shè)置以下內(nèi)容
  freezeTableName: true,

  // 定義表的名稱
  tableName: 'my_very_custom_table_name',

  // 啟用樂觀鎖定. 啟用時(shí),sequelize將向模型添加版本計(jì)數(shù)屬性,
  // 并在保存過時(shí)的實(shí)例時(shí)引發(fā)OptimisticLockingError錯(cuò)誤.
  // 設(shè)置為true或具有要用于啟用的屬性名稱的字符串.
    version: true,

  // Sequelize 實(shí)例
  sequelize,
})

如果你希望 sequelize 處理時(shí)間戳,但只想要其中一部分,或者希望你的時(shí)間戳被稱為別的東西,則可以單獨(dú)覆蓋每個(gè)列:

class Foo extends Model {}
Foo.init({ /* bla */ }, {
  // 不要忘記啟用時(shí)間戳蕊玷!
  timestamps: true,

  // 我不想要 createdAt
  createdAt: false,

  // 我想 updateAt 實(shí)際上被稱為 updateTimestamp
  updatedAt: 'updateTimestamp',

  // 并且希望 deletedA t被稱為 destroyTime(請(qǐng)記住啟用paranoid以使其工作)
  deletedAt: 'destroyTime',
  paranoid: true,

  sequelize,
})

你也可以更改數(shù)據(jù)庫引擎,例如 變更到到 MyISAM, 默認(rèn)值是 InnoDB.

class Person extends Model {}
Person.init({ /* attributes */ }, {
  engine: 'MYISAM',
  sequelize
})

// 或全局的
const sequelize = new Sequelize(db, user, pw, {
  define: { engine: 'MYISAM' }
})

最后,你可以為 MySQL 和 PG 中的表指定注釋

class Person extends Model {}
Person.init({ /* attributes */ }, {
  comment: "我是一個(gè)表注釋!",
  sequelize
})

導(dǎo)入

你還可以使用import方法將模型定義存儲(chǔ)在單個(gè)文件中. 返回的對(duì)象與導(dǎo)入文件的功能中定義的完全相同. 由于 Sequelizev1:5.0的導(dǎo)入是被緩存的,所以當(dāng)調(diào)用文件導(dǎo)入兩次或更多次時(shí),不會(huì)遇到問題.

// 在你的服務(wù)器文件中 - 例如 app.js
const Project = sequelize.import(__dirname + "/path/to/models/project")

// 模型已經(jīng)在 /path/to/models/project.js 中定義好
// 你可能會(huì)注意到,DataTypes與上述相同
module.exports = (sequelize, DataTypes) => {
  class Project extends sequelize.Model { }
  Project.init({
    name: DataTypes.STRING,
    description: DataTypes.TEXT
  }, { sequelize });
  return Project;
}

import方法也可以接受回調(diào)作為參數(shù).

sequelize.import('project', (sequelize, DataTypes) => {
  class Project extends sequelize.Model {}
  Project.init({
    name: DataTypes.STRING,
    description: DataTypes.TEXT
  }, { sequelize })
  return Project;
})

這個(gè)額外的功能也是有用的, 例如 Error: Cannot find module 被拋出,即使 /path/to/models/project 看起來是正確的. 一些框架,如 Meteor,重載 require,并給出 “驚喜” 的結(jié)果,如:

Error: Cannot find module '/home/you/meteorApp/.meteor/local/build/programs/server/app/path/to/models/project.js'

這通過傳入 Meteor 的require版本來解決. 所以,雖然這可能會(huì)失敗 ...

const AuthorModel = db.import('./path/to/models/project');

... 這應(yīng)該是成功的 ...

const AuthorModel = db.import('project', require('./path/to/models/project'));

樂觀鎖定

Sequelize 內(nèi)置支持通過模型實(shí)例版本計(jì)數(shù)的樂觀鎖定.

默認(rèn)情況下禁用樂觀鎖定,可以通過在特定模型定義或全局模型配置中將version屬性設(shè)置為 true 來啟用. 有關(guān)詳細(xì)信息,請(qǐng)參閱模型配置.

樂觀鎖定允許并發(fā)訪問模型記錄以進(jìn)行編輯,并防止沖突覆蓋數(shù)據(jù). 它通過檢查另一個(gè)進(jìn)程是否已經(jīng)讀取記錄而進(jìn)行更改,并在檢測(cè)到?jīng)_突時(shí)拋出一個(gè) OptimisticLockError.

數(shù)據(jù)庫同步

當(dāng)開始一個(gè)新的項(xiàng)目時(shí),你還不會(huì)有一個(gè)數(shù)據(jù)庫結(jié)構(gòu),并且使用 Sequelize 你也不需要它. 只需指定你的模型結(jié)構(gòu),并讓庫完成其余操作. 目前支持的是創(chuàng)建和刪除表:

// 創(chuàng)建表:
Project.sync()
Task.sync()

// 強(qiáng)制創(chuàng)建!
Project.sync({force: true}) // 這將先丟棄表,然后重新創(chuàng)建它

// 刪除表:
Project.drop()
Task.drop()

// 事件處理:
Project.[sync|drop]().then(() => {
  // 好吧...一切都很好!
}).catch(error => {
  // oooh,你輸入了錯(cuò)誤的數(shù)據(jù)庫憑據(jù)严沥?
})

因?yàn)橥胶蛣h除所有的表可能要寫很多行,你也可以讓 Sequelize 來為做這些:

// 同步所有尚未在數(shù)據(jù)庫中的模型
sequelize.sync()

// 強(qiáng)制同步所有模型
sequelize.sync({force: true})

// 刪除所有表
sequelize.drop()

// 廣播處理:
sequelize.[sync|drop]().then(() => {
  // woot woot
}).catch(error => {
  // whooops
})

因?yàn)?code>.sync({ force: true })是具有破壞性的操作,可以使用match參數(shù)作為附加的安全檢查.

match參數(shù)可以通知 Sequelize,以便在同步之前匹配正則表達(dá)式與數(shù)據(jù)庫名稱 - 在測(cè)試中使用force:true但不使用實(shí)時(shí)代碼的情況下的安全檢查.

// 只有當(dāng)數(shù)據(jù)庫名稱以'_test'結(jié)尾時(shí),才會(huì)運(yùn)行.sync()
sequelize.sync({ force: true, match: /_test$/ });

擴(kuò)展模型

Sequelize 模型是 ES6 類. 你可以輕松添加自定義實(shí)例或類級(jí)別的方法.

class User extends Model {
  // 添加一個(gè)類級(jí)別的方法
  static classLevelMethod() {
    return 'foo';
  }

  // 添加實(shí)例級(jí)別方法
  instanceLevelMethod() {
    return 'bar';
  }
}
User.init({ firstname: Sequelize.STRING }, { sequelize });

當(dāng)然,你還可以訪問實(shí)例的數(shù)據(jù)并生成虛擬的 getter:

class User extends Model {
  getFullname() {
    return [this.firstname, this.lastname].join(' ');
  }
}
User.init({ firstname: Sequelize.STRING, lastname: Sequelize.STRING }, { sequelize });

// 示例:
User.build({ firstname: 'foo', lastname: 'bar' }).getFullname() // 'foo bar'

索引

Sequelize 支持在 Model.sync()sequelize.sync 中創(chuàng)建的模型定義中添加索引.

class User extends Model {}
User.init({}, {
  indexes: [
    // 在 email 上創(chuàng)建一個(gè)唯一索引
    {
      unique: true,
      fields: ['email']
    },

    // 在使用 jsonb_path_ops 的 operator 數(shù)據(jù)上創(chuàng)建一個(gè) gin 索引
    {
      fields: ['data'],
      using: 'gin',
      operator: 'jsonb_path_ops'
    },

    // 默認(rèn)的索引名將是 [table]_[fields]
    // 創(chuàng)建多列局部索引
    {
      name: 'public_by_author',
      fields: ['author', 'status'],
      where: {
        status: 'public'
      }
    },

    // 具有有序字段的BTREE索引
    {
      name: 'title_index',
      method: 'BTREE',
      fields: ['author', {attribute: 'title', collate: 'en_US', order: 'DESC', length: 5}]
    }
  ],
  sequelize
});

索引

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市中姜,隨后出現(xiàn)的幾起案子消玄,更是在濱河造成了極大的恐慌,老刑警劉巖丢胚,帶你破解...
    沈念sama閱讀 216,372評(píng)論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件翩瓜,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡嗜桌,警方通過查閱死者的電腦和手機(jī)奥溺,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門辞色,熙熙樓的掌柜王于貴愁眉苦臉地迎上來骨宠,“玉大人浮定,你說我怎么就攤上這事〔阋冢” “怎么了桦卒?”我有些...
    開封第一講書人閱讀 162,415評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長匿又。 經(jīng)常有香客問我方灾,道長,這世上最難降的妖魔是什么碌更? 我笑而不...
    開封第一講書人閱讀 58,157評(píng)論 1 292
  • 正文 為了忘掉前任裕偿,我火速辦了婚禮,結(jié)果婚禮上痛单,老公的妹妹穿的比我還像新娘嘿棘。我一直安慰自己,他們只是感情好旭绒,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,171評(píng)論 6 388
  • 文/花漫 我一把揭開白布鸟妙。 她就那樣靜靜地躺著,像睡著了一般挥吵。 火紅的嫁衣襯著肌膚如雪重父。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,125評(píng)論 1 297
  • 那天忽匈,我揣著相機(jī)與錄音房午,去河邊找鬼。 笑死丹允,一個(gè)胖子當(dāng)著我的面吹牛歪沃,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播嫌松,決...
    沈念sama閱讀 40,028評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼沪曙,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了萎羔?” 一聲冷哼從身側(cè)響起液走,我...
    開封第一講書人閱讀 38,887評(píng)論 0 274
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎贾陷,沒想到半個(gè)月后缘眶,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,310評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡髓废,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,533評(píng)論 2 332
  • 正文 我和宋清朗相戀三年巷懈,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片慌洪。...
    茶點(diǎn)故事閱讀 39,690評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡顶燕,死狀恐怖凑保,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情涌攻,我是刑警寧澤欧引,帶...
    沈念sama閱讀 35,411評(píng)論 5 343
  • 正文 年R本政府宣布,位于F島的核電站恳谎,受9級(jí)特大地震影響芝此,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜因痛,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,004評(píng)論 3 325
  • 文/蒙蒙 一婚苹、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧鸵膏,春花似錦租副、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至赞咙,卻和暖如春责循,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背攀操。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評(píng)論 1 268
  • 我被黑心中介騙來泰國打工院仿, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人速和。 一個(gè)月前我還...
    沈念sama閱讀 47,693評(píng)論 2 368
  • 正文 我出身青樓歹垫,卻偏偏與公主長得像,于是被迫代替她去往敵國和親颠放。 傳聞我的和親對(duì)象是個(gè)殘疾皇子排惨,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,577評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容