Model definition模型定義
To define mappings between a model and a table, use the define method.定義模型和表之間的映射,使用定義方法
即project表的模型定義為有兩個字段title和description,並且其值屬性為STRING和TEXT
const Project = sequelize.define('project', { title: Sequelize.STRING, description: Sequelize.TEXT }) const Task = sequelize.define('task', { title: Sequelize.STRING, description: Sequelize.TEXT, deadline: Sequelize.DATE })
You can also set some options on each column:
const Foo = sequelize.define('foo', { // 如果沒有設置,實例化將自動設置flag為true flag: { type: Sequelize.BOOLEAN, allowNull: false, defaultValue: true }, // default values for dates => current time myDate: { type: Sequelize.DATE, defaultValue: Sequelize.NOW }, //allowNull設置為false將為每一列添加NOT NULL的設置,這意味着在執行查詢時,如果列是空的,將從數據庫拋出一個錯誤。 //如果你想在查詢數據庫之前檢查一個值非空,看看下面的validations部分。 title: { type: Sequelize.STRING, allowNull: false }, //創建兩個對象具有相同的值將拋出一個錯誤 //獨特的屬性可以是一個布爾值,或一個字符串 //如果你提供多個列相同的字符串,它們將形成一個復合唯一鍵。 uniqueOne: { type: Sequelize.STRING, unique: 'compositeIndex' }, uniqueTwo: { type: Sequelize.INTEGER, unique: 'compositeIndex' }, // The unique property is simply a shorthand to create a unique constraint.獨特的性質只是一個速記創建唯一約束 someUnique: { type: Sequelize.STRING, unique: true }, // 這與在模型選項中創建索引是完全相同的. { someUnique: { type: Sequelize.STRING } }, { indexes: [ { unique: true, fields: [ 'someUnique' ] } ] },//field既存儲在表中的鍵名 //繼續讀取更多與主鍵相關內容 identifier: { type: Sequelize.STRING, primaryKey: true }, // autoIncrement可以用來創建auto_incrementing數列 incrementMe: { type: Sequelize.INTEGER, autoIncrement: true }, //您可以通過“字段”屬性指定一個自定義字段名 fieldWithUnderscores: { type: Sequelize.STRING, field: 'field_with_underscores' }, //創建外鍵是可能的: bar_id: { type: Sequelize.INTEGER, references: { // 另一個模型的引用 model: Bar, // 引用模型的列名 key: 'id', //聲明什么時候去查看外鍵約束,只用於PostgreSQL deferrable: Sequelize.Deferrable.INITIALLY_IMMEDIATE } } })
The comment option can also be used on a table, see model configuration
Timestamps
By default, Sequelize will add the attributes createdAt and updatedAt to your model so you will be able to know when the database entry went into the db and when it was updated last.
默認情況下,Sequelize將添加屬性createdAt和updatedAt到你的模型,這樣你就可以知道什么時候進了db數據庫條目,和它最后更新的時間
Note that if you are using Sequelize migrations you will need to add the createdAt and updatedAt fields to your migration definition:
請注意,如果您使用的是Sequelize繼承需要createdAt和updatedAt字段添加到你繼承的定義中:
module.exports = {
up(queryInterface, Sequelize) {
return queryInterface.createTable('my-table', { id: { type: Sequelize.INTEGER, primaryKey: true, autoIncrement: true, }, // Timestamps createdAt: Sequelize.DATE, updatedAt: Sequelize.DATE, }) }, down(queryInterface, Sequelize) { return queryInterface.dropTable('my-table'); }, }
If you do not want timestamps on your models, only want some timestamps, or you are working with an existing database where the columns are named something else, jump straight on to configuration to see how to do that.
如果你不希望在你的模型中使用時間戳,只需要一些時間戳,或者你正在為一個現有的列正重新命名的數據庫工作,那么就直接跳轉 configuration(下面會寫)看看怎么做。
Data types
Below are some of the datatypes supported by sequelize. For a full and updated list, see DataTypes.
下面是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.ARRAY(Sequelize.ENUM) // Defines an array of ENUM. PostgreSQL only. Sequelize.JSON // JSON column. PostgreSQL, SQLite and MySQL 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.CIDR // CIDR datatype for PostgreSQL Sequelize.INET // INET datatype for PostgreSQL Sequelize.MACADDR // MACADDR datatype for PostgreSQL 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 geometry type. PostgreSQL (with PostGIS) or MySQL only. Sequelize.GEOMETRY('POINT', 4326) // Spatial column with geometry type and SRID. PostgreSQL (with PostGIS) or MySQL only.
The BLOB data type allows you to insert data both as strings and as buffers. When you do a find or findAll on a model which has a BLOB column, that data will always be returned as a buffer.
BLOB數據類型允許你插入字符串和buffer。當你在有BLOB數據類型的列的模型中進行查找時,將會返回buffer
If you are working with the PostgreSQL TIMESTAMP WITHOUT TIME ZONE and you need to parse it to a different timezone, please use the pg library's own parser:
如果你使用PostgreSQL沒有時區的時間戳,並且你需要將其解析到一個不同的時區,請用PostgreSQL庫中自己的解析器
require('pg').types.setTypeParser(1114, stringValue => { return new Date(stringValue + '+0000'); // e.g., UTC offset. Use any offset that you would like. });
In addition to the type mentioned above, integer, bigint, float and double also support unsigned and zerofill properties, which can be combined in any order: Be aware that this does not apply for PostgreSQL!
除了上面提到的類型,整數,長整型數字,浮點數和雙精度浮點數也支持無符號和補零屬性,可以在任何順序連接: 。請注意,這不用於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.INTEGER(11).UNSIGNED.ZEROFILL // INTEGER(11) UNSIGNED ZEROFILL
The examples above only show integer, but the same can be done with bigint and float
上面的示例只顯示整數,但同樣可以用長整型數字和浮動
Usage in object notation:用於對象
// for enums: sequelize.define('model', { states: { type: Sequelize.ENUM, values: ['active', 'pending', 'deleted'] } })
Array(ENUM) - Its only supported with PostgreSQL.數組(枚舉類型)只在PostgreSQL中支持
Array(Enum) type require special treatment. Whenever Sequelize will talk to database it has to typecast Array values with ENUM name.
So this enum name must follow this pattern enum_<table_name>_<col_name>. If you are using sync then correct name will automatically be generated.
Range types
Since range types have extra information for their bound inclusion/exclusion it's not very straightforward to just use a tuple to represent them in javascript.
因為范圍類型對其邊界的包含/排除(即開口和閉口)有額外信息,不容易在javascript中使用元組來表示它們。
When supplying ranges as values you can choose from the following APIs:
// defaults to '["2016-01-01 00:00:00+00:00", "2016-02-01 00:00:00+00:00")' // inclusive lower bound, exclusive upper bound,默認情況為下界為閉口[,上界為開口) Timeline.create({ range: [new Date(Date.UTC(2016, 0, 1)), new Date(Date.UTC(2016, 1, 1))] }); // control inclusion,通過inclusive來設置開閉口 const range = [new Date(Date.UTC(2016, 0, 1)), new Date(Date.UTC(2016, 1, 1))]; range.inclusive = false; // '()' range.inclusive = [false, true]; // '(]' range.inclusive = true; // '[]' range.inclusive = [true, false]; // '[)' // or as a single expression const range = [ { value: new Date(Date.UTC(2016, 0, 1)), inclusive: false }, { value: new Date(Date.UTC(2016, 1, 1)), inclusive: true }, ]; // '("2016-01-01 00:00:00+00:00", "2016-02-01 00:00:00+00:00"]' // composite form const range = [ { value: new Date(Date.UTC(2016, 0, 1)), inclusive: false }, new Date(Date.UTC(2016, 1, 1)), ]; // '("2016-01-01 00:00:00+00:00", "2016-02-01 00:00:00+00:00")' Timeline.create({ range });
However, please note that whenever you get back a value that is range you will receive:
注意,你得到的結果也是range
// stored value: ("2016-01-01 00:00:00+00:00", "2016-02-01 00:00:00+00:00"] range // [Date, Date] range.inclusive // [false, true]
Make sure you turn that into a serializable format before serialization since array extra properties will not be serialized.
因為數組額外的屬性不會被序列化,所以確保序列化之前你將其轉換成了一個可序列化的格式。
Special Cases
// empty range: Timeline.create({ range: [] }); // range = 'empty' // Unbounded range: Timeline.create({ range: [null, null] }); // range = '[,)',默認 // range = '[,"2016-01-01 00:00:00+00:00")' Timeline.create({ range: [null, new Date(Date.UTC(2016, 0, 1))] }); // Infinite range: // range = '[-infinity,"2016-01-01 00:00:00+00:00")' Timeline.create({ range: [-Infinity, new Date(Date.UTC(2016, 0, 1))] });
Deferrable可延期的
When you specify a foreign key column it is optionally possible to declare the deferrable type in PostgreSQL. The following options are available:
當你指定一個外鍵列時,可以聲明在PostgreSQL可延期的類型
// 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
The last option is the default in PostgreSQL and won't allow you to dynamically change the rule in a transaction.
最后一個選項在PostgreSQL上是默認的,不允許您動態地改變一個事務中的規則。
See the transaction section for further information.
Getters & setters
It is possible to define 'object-property' getters and setter functions on your models, these can be used both for 'protecting' properties that map to database fields and for defining 'pseudo' properties.
可以在你的模型中定義對象屬性的getter和setter函數,這些都可以用以“保護”映射到數據庫字段的屬性和定義“偽”屬性。
Getters and Setters can be defined in 2 ways (you can mix and match these 2 approaches)兩種定義方法:
- as part of a single property definition作為一個屬性定義的一部分
- as part of a model options作為一個模型的選項
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.如果一個getter或setter函數定義在兩個地方然后發現在相關屬性定義(即第一種方法)總是優先考慮。
Defining as part of a property(第一種方法)
const Employee = sequelize.define('employee', { name: { type: Sequelize.STRING, allowNull: false, get() { const 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(val) { this.setDataValue('title', val.toUpperCase()); } } }); 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 })
Defining as part of the model options(第二種方法)
Below is an example of defining the getters and setters in the model options. The fullName getter, is an example of how you can define pseudo properties on your models - attributes which are not actually part of your database schema. In fact, pseudo properties can be defined in two ways: using model getters, or by using a column with the VIRTUAL datatype. Virtual datatypes can have validations, while getters for virtual attributes cannot.
下面是一個例子,在模型選項中定義getter和setter方法。fullName這個getter是如何定義偽屬性的一個示例模型——屬性不是數據庫模式的一部分。事實上,偽屬性可以使用兩種方法進行定義:使用模型的getter方法,或者通過使用帶有一個虛擬數據類型的列。虛擬數據類型可以驗證,而虛擬屬性的getter方法不能。
Note that the this.firstname and this.lastname references in the fullName getter function will trigger a call to the respective getter functions. If you do not want that then use the getDataValue() method to access the raw value (see below).
注意在fullName這個getter函數中引用的this.firstname和this.lastname將會觸發相應的getter函數。如果你不希望getDataValue()方法去訪問原始值,就可以使用this. *(見下文)。
const Foo = 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(' ')); }, } });
Helper functions for use inside getter and setter definitions
- retrieving an underlying property value - always use
this.getDataValue()使用this.getDataValue()獲取一個基本屬性值
/* a getter for 'title' property */ get() { return this.getDataValue('title') }
- setting an underlying property value - always use
this.setDataValue()使用this.setDataValue()設置一個基本屬性值
/* a setter for 'title' property */ set(title) { this.setDataValue('title', title.toString().toLowerCase()); }
N.B: It is important to stick to using the setDataValue() and getDataValue() functions (as opposed to accessing the underlying "data values" property directly) - doing so protects your custom getters and setters from changes in the underlying model implementations.
堅持使用setDataValue()和 getDataValue()函數(而不是直接訪問底層的“數據值”屬性)是很重要的,這樣做可以保護你自定義的getter和setter以免受到底層模型實現的變化的影響。
Validations驗證
Model validations, allow you to specify format/content/inheritance validations for each attribute of the model.模型驗證,允許您為每個模型的屬性指定格式/內容/繼承的驗證。
Validations are automatically run on create, update and save. You can also call validate() to manually validate an instance.
驗證自動運行在創建、更新和保存過程中。您還可以手動調用validate()來驗證實例
The validations are implemented by validator.js.
const 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 <= 23 min: 23, // only allow values >= 23 isCreditCard: true, // check for valid credit card numbers // custom validations are also possible: isEven(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 } } } } });
Note that where multiple arguments need to be passed to the built-in validation functions, the arguments to be passed must be in an array. But if a single array argument is to be passed, for instance an array of acceptable strings for isIn, this will be interpreted as multiple string arguments instead of one array argument. To work around this pass a single-length array of arguments, such as [['one', 'two']] as shown above.
注意,在多個參數需要被傳遞給的內置的驗證函數中,被傳遞的參數必須是一個數組。但如果傳遞的是單個數組參數,例如在isIn中設置為可接受的字符串數組,這將被視為多個字符串參數,而不是單個數組參數。用以解決傳遞單個長度參數的數組,如上面所舉例子[['one', 'two']] 。
To use a custom error message instead of that provided by validator.js, use an object instead of the plain value or array of arguments, for example a validator which needs no argument can be given a custom message with
使用自定義的錯誤消息而不是提供的validator.js,使用對象來替代plain value或參數數組,比如不需要參數的驗證器可以給一個如下面的定制的消息:
isInt: { msg: "Must be an integer number of pennies" }
or if arguments need to also be passed add an args property:
或如果參數需要被傳遞,那就添加一個args屬性
isIn: { args: [['en', 'zh']], msg: "Must be English or Chinese" }
When using custom validator functions the error message will be whatever message the thrown Error object holds.
當使用自定義驗證器函數,錯誤消息將是拋出的錯誤對象中的任何消息
See the validator.js project for more details on the built in validation methods.
Hint: You can also define a custom function for the logging part. Just pass a function. The first parameter will be the string that is logged.
您還可以定義一個自定義函數用以記錄。僅僅通過一個函數。第一個參數是記錄的字符串
Validators and allowNull
If a particular field of a model is set to allow null (with allowNull: true) and that value has been set to null, its validators do not run. This means you can, for instance, have a string field which validates its length to be at least 5 characters, but which also allows null.
如果一個特定領域模型設置為允許null(allowNull:真實),該值被設置為null,其驗證器不運行。舉例來說,這意味着您可以有一個驗證字符串字段的長度至少5個字符,但是也allowsnull。
如果模型的特定字段被設置為允許null(有着設置allowNull: true),則其值將會被設置誒null,驗證器將不會運行。舉例來說,這意味着您可以有一個字符串字段驗證其長度至少5個字符,但是同時也允許其值為null。
Model validations
Validations can also be defined to check the model after the field-specific validators. Using this you could, for example, ensure either neither of latitude and longitude are set or both, and fail if one but not the other is set.
驗證也可以在具體字段的驗證器后被定義去檢查模型(如下面例子的bothCoordsOrNone函數就是在latitude和longitude具體字段驗證器后定義的驗證)。例如,使用這個可以確保要么latitude和longitude都沒有被設置或兩者都被設置,如果一個設置而另一個沒有則失敗(下面的例子)
Model validator methods are called with the model object's context and are deemed to fail if they throw an error, otherwise pass. This is just the same as with custom field-specific validators.
模型驗證器方法與模型對象的上下文一起被調用,並拋出錯誤則認為失敗,否則通過。這與自定義具體字段的驗證器是相同的。
Any error messages collected are put in the validation result object alongside the field validation errors, with keys named after the failed validation method's key in the validate option object. Even though there can only be one error message for each model validation method at any one time, it is presented as a single string error in an array, to maximize consistency with the field errors.
收集的任何錯誤消息將被放到帶着驗證錯誤字段的驗證結果對象中,並帶着在驗證選項對象中經過失敗的驗證方法的鍵值后命名的鍵值。即使在任何時候,對於每個模型驗證方法只能有一個錯誤信息,它是作為在數組中的一個字符串錯誤,並最大化錯誤字段的一致性。
An example:
const 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() { if ((this.latitude === null) !== (this.longitude === null)) { throw new Error('Require either both latitude and longitude or neither') } } } })
In this simple case an object fails validation if either latitude or longitude is given, but not both.
If we try to build one with an out-of-range latitude and no longitude, raging_bullock_arms.validate() might return:如果創建超出范圍的latitude並不設置longitude,則會報下面的錯:
{ 'latitude': ['Invalid number: latitude'], 'bothCoordsOrNone': ['Require either both latitude and longitude or neither'] }
Configuration
You can also influence the way Sequelize handles your column names:
影響Sequelize處理你的列名的方式
const Bar = sequelize.define('bar', { /* bla */ }, { // 不添加時間戳屬性(updatedAt, createdAt) timestamps: false, // 不刪除數據庫的條目,但是在目前的日期中添加deletedAt屬性,在delete完成時,即(updatedAt, createdAt, deletedAt) // paranoid只在timestamps為true時可用 paranoid: true, //自動添加屬性將不使用camelcase(一種拼寫法),而是使用下划線風格 //即從updatedAt變為updated_at underscored: true, //即不允許表名的修改 //默認情況下,sequelize將會自動將通過的模型名(即定義的第一個參數)轉成復數形式 //如果你不想這么做,就進行下面的設置 freezeTableName: true, // define the table's name,定義表名 tableName: 'my_very_custom_table_name', //Enable optimistic locking(下面有說) //當enabled時,sequelize將添加版本計數屬性到模型上,並在失效實例被保存時拋出OptimisticLockingError錯誤 //當你想要enable optimistic locking時,將其設置為true或帶有屬性名的字符串 version: true })
If you want sequelize to handle timestamps, but only want some of them, or want your timestamps to be called something else, you can override each column individually:
如果你想要sequelize處理時間戳,但是有只想要時間戳的一部分(下面只要),或者你想要時間戳能夠被別的調用(下面設置為可被updatedAt調用),你可以單獨覆寫每一列:updateTimestamp
const Foo = sequelize.define('foo', { /* bla */ }, { // don't forget to enable timestamps! timestamps: true, // I don't want createdAt createdAt: false, // I want updatedAt to actually be called updateTimestamp updatedAt: 'updateTimestamp', // And deletedAt to be called destroyTime (remember to enable paranoid for this to work) deletedAt: 'destroyTime', paranoid: true })
You can also change the database engine, e.g. to MyISAM. InnoDB is the default.
你也可以改變數據庫引擎,默認是MyISAM. InnoDB
const Person = sequelize.define('person', { /* attributes */ }, { engine: 'MYISAM' }) // or globally const sequelize = new Sequelize(db, user, pw, { define: { engine: 'MYISAM' } })
Finally you can specify a comment for the table in MySQL and PG
最后你可以在MySQL和 PG數據庫的表中發表評價
const Person = sequelize.define('person', { /* attributes */ }, { comment: "I'm a table comment!" })
Optimistic Locking
Sequelize has built-in support for optimistic locking through a model instance version count. Optimistic locking is disabled by default and can be enabled by setting the version property to true in a specific model definition or global model configuration. See model configuration for more details.
Sequelize通過模型實例版本計數來內置支持optimistic locking(如上面的設置version: true)。Optimistic locking默認是不可用的,然后能夠在具體模型定義或全局模型配置中通過設置version屬性為true來使其可行。
Optimistic locking allows concurrent access to model records for edits and prevents conflicts from overwriting data. It does this by checking whether another process has made changes to a record since it was read and throws an OptimisticLockError when a conflict is detected.
Optimistic locking允許並發訪問用以編輯和防止覆蓋數據的沖突的模型記錄。它通過檢查另一個進程是否在其讀取時已更改記錄和當檢測到沖突時拋出一個OptimisticLockError來實現。
Import
You can also store your model definitions in a single file using the import method. The returned object is exactly the same as defined in the imported file's function. Since v1:5.0 of Sequelize the import is cached, so you won't run into troubles when calling the import of a file twice or more often.
你可以使用import方法存儲你的模型定義到一個文件中。返回對象與定義在導入文件的函數中的是相同的。從v1:5.0版本開始Sequelize的導入為緩存,所以當你導入一個文件兩次或更多次時,也不會導致問題出現
// in your server file - e.g. app.js const Project = sequelize.import(__dirname + "/path/to/models/project") // The model definition is done in /path/to/models/project.js // As you might notice, the DataTypes are the very same as explained above module.exports = (sequelize, DataTypes) => { return sequelize.define("project", { name: DataTypes.STRING, description: DataTypes.TEXT }) }
The import method can also accept a callback as an argument.
import方法也接受回調函數作為參數
sequelize.import('project', (sequelize, DataTypes) => { return sequelize.define("project", { name: DataTypes.STRING, description: DataTypes.TEXT }) })
This extra capability is useful when, for example, Error: Cannot find module is thrown even though /path/to/models/project seems to be correct. Some frameworks, such as Meteor, overload require, and spit out "surprise" results like :
Error: Cannot find module '/home/you/meteorApp/.meteor/local/build/programs/server/app/path/to/models/project.js'
This is solved by passing in Meteor's version of require. So, while this probably fails ...
const AuthorModel = db.import('./path/to/models/project');
... this should succeed ...
const AuthorModel = db.import('project', require('./path/to/models/project'));
Database synchronization同步數據庫
When starting a new project you won't have a database structure and using Sequelize you won't need to. Just specify your model structures and let the library do the rest. Currently supported is the creation and deletion of tables:
當開始一個新項目時,你還沒有數據庫且不需要使用Sequelize。只要指定你的模型結構,然后剩下的就讓庫去處理。
目前只支持創建和刪除表:
之前已經定義了表的模型,調用.sync()將會創建表並且返回一個Promise對象
// Create the tables: Project.sync() Task.sync() // Force the creation! force: true將會刪掉原來的表並重新生成表 Project.sync({force: true}) // this will drop the table first and re-create it afterwards // drop the tables:刪除表 Project.drop() Task.drop() // event handling:監聽sync|drop事件 Project.[sync|drop]().then(() => { // ok ... everything is nice! }).catch(error => { // oooh, did you enter wrong database credentials? })
Because synchronizing and dropping all of your tables might be a lot of lines to write, you can also let Sequelize do the work for you:
因為同步或刪除你的所有表將需要寫很多行,你可以讓Sequelize幫你做這件事:
// Sync all models that aren't already in the database sequelize.sync() // Force sync all models sequelize.sync({force: true}) // Drop all tables sequelize.drop() // emit handling: sequelize.[sync|drop]().then(() => { // woot woot }).catch(error => { // whooops })
Because .sync({ force: true }) is destructive operation, you can use match option as an additional safety check. match option tells sequelize to match a regex against the database name before syncing - a safety check for cases where force: true is used in tests but not live code.
因為.sync({ force: true })是毀滅性操作,你可以使用match選項作為額外安全檢查。match選項告訴sequelize在同步前去匹配與數據庫名字相關的正則表達式-它是當例子設置為force: true時的安全性的檢查,只用於測試,而不是代碼
// This will run .sync() only if database name ends with '_test' sequelize.sync({ force: true, match: /_test$/ });
Expansion of models模型擴展
Sequelize Models are ES6 classes. You can very easily add custom instance or class level methods.
Sequelize模型是ES6類。你可以很容易地添加自定義實例級或者類級方法
const User = sequelize.define('user', { firstname: Sequelize.STRING }); // Adding a class level method,類級 User.classLevelMethod = function() { return 'foo'; }; // Adding an instance level method,實例級 User.prototype.instanceLevelMethod = function() { return 'bar'; };
Of course you can also access the instance's data and generate virtual getters:
你可以訪問實例數據和生成虛擬getters函數:
const User = sequelize.define('user', { firstname: Sequelize.STRING, lastname: Sequelize.STRING }); User.prototype.getFullname = function() { return [this.firstname, this.lastname].join(' '); }; // Example: User.build({ firstname: 'foo', lastname: 'bar' }).getFullname() // 'foo bar'
Indexes索引
Sequelize supports adding indexes to the model definition which will be created during Model.sync() or sequelize.sync.
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}] } ] })
