模型属性是关于模型的基本信息片段。例如,名为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 | [电子邮件保护] | Mike McNeil | ranchdressing |
14 | [电子邮件保护] | 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 的替代方案,你可能需要考虑将它们流式传输到磁盘或远程文件系统(如 S3),使用.upload()
方法.- 请记住,MySQL 中的自定义列选项(如
CHARACTER SET utf8mb4
)会影响列的存储大小。这与unique
属性一起使用时尤其重要,在这种情况下,你可能需要指定更小的列大小以避免错误。有关更多信息,请参见下面的unique
属性 文档。
将属性设置为自动增量键。当向模型添加新记录时,如果未指定此属性的值,它将通过将最近记录的值加 1 来生成。注意:指定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
。