模型屬性是有關模型的基本資訊。例如,一個名為 Person
的模型可能具有名為 firstName
、lastName
、phoneNumber
、age
、birthDate
和 emailAddress
的屬性。
模型的 attributes
設定 允許您提供一組屬性,每個屬性都定義為字典(一個純 JavaScript 物件)。
// api/models/User.js
{
attributes: {
emailAddress: { type: 'string', required: true, },
karma: { type: 'number', },
isSubscribedToNewsletter: { type: 'boolean', defaultsTo: true, },
},
}
在每個屬性中,都有一個或多個鍵(或選項),用於為 Sails 和 Waterline 提供額外的指示。這些屬性鍵告訴模型如何確保型別安全、實施高階驗證規則,以及(如果您已啟用自動遷移)如何在您的資料庫中設定表格或集合。
您還可以定義預設屬性,這些屬性將出現在您 *所有* 的模型中,方法是將 attributes
定義為 預設模型設定(例如,在 config/models.js
中)。例如,新的 Sails 應用程式預設帶有三個預設屬性:id
、createdAt
和 updatedAt
。
除非預設屬性被覆寫或停用,否則這些屬性將在所有模型中可用。要覆寫預設屬性,請在模型定義中定義一個具有相同名稱的屬性。要 *停用* 預設屬性,請將其定義為 false
。例如,要停用特定模型的預設 updatedAt
屬性
// api/models/ProductCategory.js
module.exports = {
attributes: {
updatedAt: false,
label: { type: 'string', required: true },
}
}
除了 關聯 之外,每個屬性都必須宣告一個 type
。
這是將為此屬性儲存的資料型別,並用於查詢和結果的邏輯型別安全檢查。以下是 Sails 和 Waterline 支援的資料型別列表
如果屬性為 required: true
,則在呼叫 .create()
時,必須始終為其指定一個值。這可以防止屬性值被建立為或更新為 null
或空字串("")。
除了五種資料型別之外,您還可以為屬性定義其他幾個基本保證;其中之一是為其指定預設值的能力。
屬性的預設值 (defaultsTo
) 僅在 .create()
上適用,且僅在完全省略鍵時適用。
attributes: {
phoneNumber: {
type: 'string',
defaultsTo: '111-222-3333'
}
}
string
、number
和 boolean
資料型別在建立或更新記錄時 *不* 接受 null
作為值。為了允許設定 null
值,您可以切換屬性上的 allowNull
標誌。請注意,allowNull
標誌僅在上面列出的資料型別上有效。它在型別為 json
或 ref
的屬性、任何關聯或任何主鍵屬性上 *無效*。
attributes: {
phoneNumber: {
type: 'string',
allowNull: true
}
}
除了基本的型別安全檢查之外,Sails 還提供幾種不同的高階驗證規則。例如,isIn
規則驗證為此屬性儲存的任何新值都必須 *完全符合* 幾個不同的硬編碼常數之一
unsubscribeReason: {
type: 'string',
isIn: ['boring', 'too many emails', 'recipes too difficult', 'other'],
required: true
}
有關高階驗證規則的完整列表,請參閱 驗證。
在屬性定義中,您可以指定 columnName
以強制 Sails/Waterline 將該屬性的資料儲存在已配置的資料儲存區(即資料庫)中的特定欄位中。請注意,這不一定特定於 SQL,它也適用於 MongoDB 欄位等。
雖然 columnName
屬性主要設計用於處理現有/舊版資料庫,但在您的資料庫正由其他應用程式共用,或者您沒有變更結構描述的存取權限的情況下,它也可能很有用。
為了將模型的 numberOfWheels
屬性儲存/提取到/從 number_of_round_rotating_things
欄位
// An attribute in one of your models:
// ...
numberOfWheels: {
type: 'number',
columnName: 'number_of_round_rotating_things'
}
// ...
現在來看一個更全面的範例。
假設您的 Sails 應用程式中有一個 User
模型,如下所示
// api/models/User.js
module.exports = {
datastore: 'shinyNewMySQLDatabase',
attributes: {
name: {
type: 'string'
},
password: {
type: 'string'
},
email: {
type: 'string',
unique: true
}
}
};
一切運作良好,但是,與其使用位於某處伺服器上的現有 MySQL 資料庫,該資料庫碰巧存放您應用程式的目標使用者...
// config/datastores.js
module.exports = {
// ...
// Existing users are in here!
rustyOldMySQLDatabase: {
adapter: 'sails-mysql',
url: 'mysql://ofh:[email protected]/jonas'
},
// ...
};
... 假設舊的 MySQL 資料庫中有名為 our_users
的表格,如下所示
the_primary_key | email_address | full_name | seriously_hashed_password |
---|---|---|---|
7 | [email protected] | Mike McNeil | ranchdressing |
14 | [email protected] | Nick Crumrine | thousandisland |
為了從 Sails 使用此資料庫,您需要將 User
模型變更為如下所示
// api/models/User.js
module.exports = {
datastore: 'rustyOldMySQLDatabase',
tableName: 'our_users',
attributes: {
id: {
type: 'number',
unique: true,
columnName: 'the_primary_key'
},
name: {
type: 'string',
columnName: 'full_name'
},
password: {
type: 'string',
columnName: 'seriously_hashed_password'
},
email: {
type: 'string',
unique: true,
columnName: 'email_address'
}
}
};
您可能已經注意到,在這個範例中,我們也使用了
tableName
屬性。這讓我們可以控制將用於存放我們資料的表格名稱。
設定 encrypt
可讓您決定是否應自動加密此屬性。如果設定為 true
,則在檢索記錄時,除非使用 .decrypt()
,否則它仍將包含此屬性的加密值。
attributes: {
ssn: {
type: 'string',
encrypt: true
}
}
如果您對屬性使用
encrypt: true
,則將無法通過未加密的值查找記錄。
這些設定用於指示 Sails 在應用程式啟動時應如何為屬性建立實體層級(例如 PostgreSQL、MySQL 或 MongoDB)資料庫欄位。
當模型的
migrate
屬性設定為safe
時,這些設定將被忽略,並且資料庫欄位將保持不變。
指示當 Sails 建立資料庫表格時,要用於屬性的實體層級欄位資料型別。這允許您指定直接與底層資料庫如何建立它們相關聯的型別。例如,您可能有一個屬性將其 type
屬性設定為 number
,並且為了將其儲存在資料庫中,您想要使用欄位型別 float
。您的屬性定義將如下所示
attributes: {
placeInLine: {
type: 'number',
columnType: 'float'
}
}
- 欄位型別完全依賴於資料庫。請確保您選擇的
columnType
對應於對您的資料庫有效的資料型別!如果您未指定columnType
,則轉接器將根據屬性的type
為您選擇一個。columnType
值在建立資料庫欄位的語句中逐字使用,因此您可以使用它來指定其他選項,例如varchar(255) CHARACTER SET utf8mb4
。- 如果您打算在 Sails 模型中儲存二進制資料,則需要將屬性的
type
設定為ref
,然後為您選擇的資料庫使用適當的columnType
(例如,MySQL 的mediumblob
或 PostgreSQL 的bytea
)。請記住,您嘗試儲存的任何內容都必須先適合記憶體,然後才能傳輸到資料庫,因為目前 Sails 中沒有機制將二進制資料串流到資料儲存區轉接器。作為將 blob 儲存在資料庫中的替代方案,您可以考慮使用.upload()
方法 將它們串流到磁碟或像 S3 這樣的遠端檔案系統。- 請記住,MySQL 中像
CHARACTER SET utf8mb4
這樣的自訂欄位選項可能會影響欄位的儲存大小。當與unique
屬性結合使用時,這尤其相關,在這種情況下,您可能需要指定較小的欄位大小以避免錯誤。有關更多資訊,請參閱下面的unique
屬性 文件。
將屬性設定為自動遞增鍵。當新記錄被新增到模型時,如果未指定此屬性的值,它將通過將最新記錄的值遞增一來產生。注意:指定 autoIncrement
的屬性應始終為 type: 'number'
。另請記住,不同資料儲存區的支援程度有所不同。例如,MySQL 不允許每個表格有多個自動遞增欄位。
attributes: {
placeInLine: {
type: 'number',
autoIncrement: true
}
}
確保不允許兩個記錄的目標屬性具有相同的值。這是一個轉接器層級的約束,因此在大多數情況下,這將導致在底層資料儲存區中為屬性建立唯一索引。
attributes: {
username: {
type: 'string',
unique: true
}
}
根據您的資料庫,當使用 unique: true
時,您可能還需要設定 required: true
。
當在 MySQL 資料庫中對具有
utf8mb4
字元集的屬性使用unique: true
時,您將需要通過columnType
屬性 手動設定欄位大小,以避免可能的「索引過長」錯誤。例如:columnType: varchar(100) CHARACTER SET utf8mb4
。