数据模型
目录
1. 概述
Yao 数据模型是应用的核心组件,它使系统能够:
- 自动数据迁移:根据模型定义创建和更新数据库表结构
- 元数据原子操作:提供标准化的数据操作方法
- 数据校验:基于模型定义进行输入数据的合法性验证
- 自动管理后台:生成数据管理界面
数据模型将操作方法映射为处理器(process
),可在数据流(Flow
)和接口(API
)中直接调用。对于使用golang
开发的业务插件,可通过Gou
包访问模型方法。
2. 命名规范
数据模型使用小写英文字母命名的JSON文件:<name>.mod.json
文件位置 | 文件名 | 模型名称 | 处理器调用方式 |
---|---|---|---|
/ | name.mod.json | name | models.name.<process> |
/group/ | name.mod.json | group.name | models.group.name.<process> |
/group1/group2/ | name.mod.json | group1.group2.name | models.group1.group2.name.<process> |
3. 文档结构
数据模型定义文件包含以下主要部分:
json
{
"name": "用户", // 模型中文名称
"table": {}, // 数据表定义
"columns": [], // 字段定义
"indexes": [], // 索引定义
"relations": {}, // 关系映射
"values": [], // 默认数据
"option": {} // 配置选项
}
字段 | 类型 | 说明 | 必填 |
---|---|---|---|
name | String | 模型中文名称 | ✓ |
table | Object | 数据表定义 | ✓ |
columns | Array<Object> | 字段定义 | ✓ |
indexes | Array<Object> | 索引定义 | ✓ |
relations | [key:String]:Object | 关系映射 | ✗ |
values | Array<Object> | 默认数据 | ✗ |
option | Object | 配置选项 | ✗ |
3.1 基础信息
基础信息用于描述模型的元数据,便于在开发平台中管理和检索。
json
{
"name": "用户",
"version": "1.0.0",
"description": "网站用户元数据模型",
"author": "开发者姓名",
"email": "developer@example.com",
"license": "MIT"
}
字段 | 类型 | 说明 | 必填 |
---|---|---|---|
name | String | 中文名称 | ✓ |
version | String | 遵循语义化版本的版本号 | ✓ |
description | String | 详细介绍 | ✗ |
author | String | 作者 | ✗ |
String | 联系方式 | ✗ | |
license | String | 共享协议 | ✗ |
homepage | String | 官网 | ✗ |
tun | String | 象传智慧共享仓库地址,如microcity/petstore/user | ✗ |
3.2 数据表 table
定义模型对应的数据库表结构。
json
{
"table": {
"name": "user", // 表名
"comment": "用户表", // 表注释
"engine": "InnoDB" // 数据表引擎(MySQL)
}
}
字段 | 类型 | 说明 | 必填 |
---|---|---|---|
name | String | 数据表名称 | ✓ |
comment | String | 数据表注释 | ✗ |
engine | String | 表引擎(MySQL),可选值:InnoDB 、MyISAM | ✗ |
3.3 字段定义 columns
字段定义包含模型的各个属性及其验证规则。
json
{
"columns": [
{
"label": "ID",
"name": "id",
"type": "ID"
},
{
"label": "用户名",
"name": "username",
"type": "string",
"length": 50,
"comment": "登录用户名",
"nullable": false,
"unique": true,
"validations": [
{
"method": "typeof",
"args": ["string"],
"message": "用户名必须是字符串"
},
{
"method": "minLength",
"args": [3],
"message": "用户名至少需要3个字符"
}
]
}
]
}
字段基本属性
字段 | 类型 | 说明 | 必填 |
---|---|---|---|
name | String | 字段名称 | ✓ |
type | String | 字段类型 | ✓ |
label | String | 显示名称 | ✓ |
comment | String | 字段注释 | ✗ |
length | Integer | 字段长度(适用于string等类型) | ✗ |
precision | Integer | 数值总位数(适用于float等) | ✗ |
scale | Integer | 小数位位数(适用于float等) | ✗ |
option | Array<String> | 枚举类型选项 | ✗ |
default | 任意 | 默认值 | ✗ |
default_raw | String | 原始默认值(支持SQL函数) | ✗ |
nullable | Boolean | 是否可为空(默认false) | ✗ |
index | Boolean | 是否为索引(默认false) | ✗ |
unique | Boolean | 是否为唯一索引(默认false) | ✗ |
primary | Boolean | 是否为主键(默认false) | ✗ |
crypt | String | 加密方式,可选值:AES 、PASSWORD | ✗ |
validations | Array<Object> | 验证规则 | ✗ |
字段类型对照表
类型 | 说明 | 参数 | MySQL对应类型 |
---|---|---|---|
string | 字符串 | length | VARCHAR(length) |
text | 文本 | - | TEXT |
integer | 整型 | - | INT |
ID/id | 自增长整型 | - | BIGINT UNSIGNED AUTO_INCREMENT |
float | 浮点数 | precision, scale | FLOAT(precision,scale) |
decimal | 精确小数 | precision, scale | DECIMAL(precision,scale) |
boolean | 布尔型 | - | BOOLEAN |
enum | 枚举型 | option | ENUM(option...) |
date | 日期 | - | DATE |
datetime | 日期时间 | - | DATETIME |
timestamp | 时间戳 | - | TIMESTAMP |
json/JSON | JSON数据 | - | JSON |
完整字段类型列表请参考文档后面的详细说明
数据验证规则
验证规则用于在数据创建和更新时检查字段值的合法性。
json
{
"validations": [
{
"method": "typeof", // 验证方法
"args": ["string"], // 方法参数
"message": "必须是字符串" // 错误提示
}
]
}
验证方法 | 参数 | 说明 | 示例 |
---|---|---|---|
typeof | [类型] | 检查数据类型 | {"method":"typeof", "args":["integer"]} |
min | [最小值] | 最小值检查 | {"method":"min", "args":[0]} |
max | [最大值] | 最大值检查 | {"method":"max", "args":[100]} |
enum | [选项...] | 枚举值检查 | {"method":"enum", "args":["enabled","disabled"]} |
pattern | [正则表达式] | 正则匹配 | {"method":"pattern", "args":["^1[3-9]\\d{9}$"]} |
minLength | [长度] | 最小长度 | {"method":"minLength", "args":[6]} |
maxLength | [长度] | 最大长度 | {"method":"maxLength", "args":[18]} |
[] | 邮箱格式 | {"method":"email", "args":[]} | |
mobile | [地区] | 手机号格式 | {"method":"mobile", "args":["cn"]} |
错误消息支持模板变量:
- 用户输入的值
- 字段标签
字段加密
支持两种加密方式保护敏感数据:
加密方式 | 说明 | 可逆性 |
---|---|---|
AES | AES加密(需设置环境变量XIANG_DB_AESKEY ) | 可逆 |
PASSWORD | 密码哈希加密 | 不可逆 |
3.4 索引定义 indexes
索引用于提高查询性能和保证数据唯一性。
json
{
"indexes": [
{
"name": "user_email_mobile_unique", // 索引名称
"type": "unique", // 索引类型
"columns": ["email", "mobile"], // 索引字段
"comment": "用户邮箱和手机号唯一" // 索引说明
}
]
}
字段 | 类型 | 说明 | 必填 |
---|---|---|---|
name | String | 索引名称(建议格式:字段1字段2..._索引类型) | ✓ |
type | String | 索引类型:index 、unique 、primary 、fulltext | ✓ |
columns | Array<String> | 索引字段名称列表(顺序有关) | ✓ |
comment | String | 索引注释 | ✗ |
3.5 关系映射 relations
关系映射定义模型之间的关联关系,支持一对一、一对多、多对多等多种映射方式。
json
{
"relations": {
"profile": {
// 关联名称
"type": "hasOne", // 关系类型
"model": "user_profile", // 关联模型
"key": "user_id", // 关联模型的关联字段
"foreign": "id", // 当前模型的关联字段
"query": {
// 默认查询参数
"select": ["avatar", "bio"]
}
}
}
}
关系类型
关系类型 | 说明 | 用途 |
---|---|---|
hasOne | 一对一关系 | 用户-资料、产品-详情 |
hasMany | 一对多关系 | 用户-订单、文章-评论 |
hasOneThrough | 跨表一对一 | 复杂的间接关联 |
hasManyThrough | 跨表一对多 | 用户-角色-权限 |
关系定义字段
字段 | 类型 | 说明 | 必填 |
---|---|---|---|
type | String | 关系类型 | ✓ |
model | String | 关联模型名称 | ✓ (简单关系) |
key | String | 关联模型关联字段 | ✓ (简单关系) |
foreign | String | 当前模型关联字段 | ✓ (简单关系) |
query | Object | 默认查询参数 | ✗ |
links | Array<Object> | 多表关联定义 | ✓ (跨表关系) |
实际应用示例
一对一关系(hasOne):
json
{
"manu": {
"type": "hasOne",
"model": "manu",
"key": "id",
"foreign": "manu_id",
"query": { "select": ["name", "short_name"] }
}
}
一对多关系(hasMany):
json
{
"addresses": {
"type": "hasMany",
"model": "address",
"key": "user_id",
"foreign": "id",
"query": {
"select": ["province", "city", "location"],
"limit": 20
}
}
}
3.6 默认数据 values
定义模型的初始数据,在首次迁移时自动插入。
json
{
"values": [
{
"name": "管理员",
"email": "admin@example.com",
"password": "Admin@123",
"type": "admin",
"status": "enabled"
}
]
}
3.7 配置选项 option
定义模型的全局配置参数。
json
{
"option": {
"timestamps": true, // 自动添加时间戳字段
"soft_deletes": true // 启用软删除
}
}
选项 | 类型 | 说明 |
---|---|---|
timestamps | Boolean | 添加created_at 和updated_at 字段并自动维护 |
soft_deletes | Boolean | 添加deleted_at 字段实现软删除功能 |
4. 查询参数 QueryParam
查询参数用于在关系定义和API调用中描述数据过滤、排序和关联查询条件。
json
{
"select": ["id", "name", "mobile"], // 查询字段
"wheres": [
// 查询条件
{ "column": "status", "value": "enabled" }
],
"orders": [
// 排序条件
{ "column": "id", "option": "desc" }
],
"withs": {
// 关联查询
"profile": { "select": ["avatar"] }
},
"limit": 10, // 返回记录数
"page": 1, // 页码
"pagesize": 20 // 每页记录数
}
查询条件格式
json
{
"wheres": [
{
"column": "status", // 字段名
"value": "enabled", // 匹配值
"op": "eq", // 操作符(可选,默认eq)
"method": "where" // 方法(可选,默认where)
},
{
"rel": "profile", // 关联模型名
"column": "is_verified", // 关联模型字段
"value": true
},
{
"wheres": [
// 分组条件(OR)
{ "column": "name", "value": "%张%", "op": "like" },
{ "method": "orwhere", "column": "name", "value": "%李%", "op": "like" }
]
}
]
}
常用操作符
操作符 | 说明 | SQL等价 |
---|---|---|
eq | 等于(默认) | field = value |
like | 模糊匹配 | field LIKE value |
gt | 大于 | field > value |
ge | 大于等于 | field >= value |
lt | 小于 | field < value |
le | 小于等于 | field <= value |
in | 包含 | field IN (values) |
null | 为空 | field IS NULL |
notnull | 不为空 | field IS NOT NULL |
5. 处理器(process
)
数据模型自动生成以下处理器,可在API和Flow中使用:
处理器 | 调用方式 | 功能 |
---|---|---|
find | models.模型名.find | 查询单条记录 |
get | models.模型名.get | 按条件查询(不分页) |
paginate | models.模型名.paginate | 按条件查询(分页) |
create | models.模型名.create | 创建单条记录 |
update | models.模型名.update | 更新单条记录 |
save | models.模型名.save | 保存记录(存在则更新,不存在则创建) |
delete | models.模型名.delete | 删除单条记录(软删除) |
destroy | models.模型名.destroy | 删除单条记录(物理删除) |
insert | models.模型名.insert | 批量插入记录 |
updatewhere | models.模型名.updatewhere | 按条件更新记录 |
deletewhere | models.模型名.deletewhere | 按条件删除记录(软删除) |
destroywhere | models.模型名.destroywhere | 按条件删除记录(物理删除) |
eachsave | models.模型名.eachsave | 批量保存记录 |
6. 完整示例
以下是一个完整的用户模型定义示例:
json
{
"name": "用户",
"table": {
"name": "user",
"comment": "用户信息表",
"engine": "InnoDB"
},
"columns": [
{ "label": "ID", "name": "id", "type": "ID" },
{
"label": "用户名",
"name": "username",
"type": "string",
"length": 50,
"unique": true,
"comment": "登录用户名",
"validations": [
{
"method": "typeof",
"args": ["string"],
"message": "{{label}}必须是字符串"
},
{
"method": "minLength",
"args": [3],
"message": "{{label}}长度至少为3个字符"
}
]
},
{
"label": "密码",
"name": "password",
"type": "string",
"length": 256,
"comment": "登录密码",
"crypt": "PASSWORD",
"validations": [
{
"method": "pattern",
"args": [
"^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)(?=.*[@$!%*?&])[A-Za-z\\d@$!%*?&]{8,}$"
],
"message": "{{label}}必须包含大小写字母、数字和特殊字符,且长度不少于8位"
}
]
},
{
"label": "状态",
"name": "status",
"type": "enum",
"option": ["active", "inactive", "banned"],
"default": "inactive",
"comment": "用户状态",
"index": true
}
],
"indexes": [
{
"name": "username_status_index",
"comment": "用户名和状态联合索引",
"columns": ["username", "status"],
"type": "index"
}
],
"relations": {
"profile": {
"type": "hasOne",
"model": "user_profile",
"key": "user_id",
"foreign": "id"
},
"orders": {
"type": "hasMany",
"model": "order",
"key": "user_id",
"foreign": "id",
"query": { "limit": 10 }
}
},
"values": [
{
"username": "admin",
"password": "Admin@123",
"status": "active"
}
],
"option": {
"timestamps": true,
"soft_deletes": true
}
}