数据模型关联
基本概念
Yao DSL支持两种数据模型关联类型:
- hasOne:一对一关联,表示当前模型的一条记录对应关联模型的一条记录
- hasMany:一对多关联,表示当前模型的一条记录对应关联模型的多条记录
通过使用withs参数,可以在查询时同时获取关联数据,避免多次查询,提高效率。
实例说明
以下我们通过供应商(supplier
)和用户(user
)两个模型演示关联关系:
- 一个用户对应一家供应商 (用户 -> 供应商 = hasOne)
- 一家供应商有多个用户 (供应商 -> 用户 = hasMany)
数据结构设计
供应商模型 (supplier
)
字段结构:
字段 | 标签 | 说明 |
---|---|---|
id | ID | 主键 |
name | 名称 | 供应商名称 |
示例数据:
ID | 名称 |
---|---|
1 | 象传智慧 |
2 | Yao App Engine |
用户模型 (user
)
字段结构:
字段 | 标签 | 说明 |
---|---|---|
id | ID | 主键 |
supplier_id | 所属供应商 ID | 外键,关联供应商表 |
name | 姓名 | 用户姓名 |
示例数据:
ID | supplier_id | name |
---|---|---|
1 | 1 | 张无忌 |
2 | 1 | 李光富 |
3 | 2 | 李木婷 |
4 | 2 | 赵长青 |
模型定义文件
供应商模型定义 (supplier.mod.json
)
json
{
"name": "供应商",
"table": { "name": "supplier", "comment": "供应商表" },
"columns": [
{
"label": "ID",
"name": "id",
"type": "ID",
"comment": "ID"
},
{
"label": "名称",
"name": "name",
"type": "string",
"index": true,
"comment": "供应商名称"
}
],
"relations": {
"users": {
"name": "users", // 关联名称,查询时通过此名称引用
"type": "hasMany", // 关系类型:一对多
"model": "user", // 关联的模型名称
"key": "supplier_id", // 关联模型中的关联字段
"foreign": "id", // 当前模型中的关联字段
"query": { "select": ["id", "name"] } // 默认查询字段
}
},
"values": [
{ "id": 1, "name": "象传智慧" },
{ "id": 2, "name": "Yao App Engine" }
]
}
用户模型定义 (user.mod.json
)
json
{
"name": "用户",
"table": { "name": "user", "comment": "用户表" },
"columns": [
{ "label": "ID", "name": "id", "type": "ID", "comment": "ID" },
{
"label": "供应商",
"name": "supplier_id",
"type": "bigInteger",
"index": true,
"comment": "供应商ID"
},
{
"label": "姓名",
"name": "name",
"type": "string",
"index": true,
"comment": "用户姓名"
}
],
"relations": {
"supplier": {
"name": "supplier", // 关联名称,查询时通过此名称引用
"type": "hasOne", // 关系类型:一对一
"model": "supplier", // 关联的模型名称
"key": "id", // 关联模型中的关联字段
"foreign": "supplier_id", // 当前模型中的关联字段
"query": { "select": ["id", "name"] } // 默认查询字段
}
},
"values": [
{ "id": 1, "supplier_id": 1, "name": "张无忌" },
{ "id": 2, "supplier_id": 1, "name": "李光富" },
{ "id": 3, "supplier_id": 2, "name": "李木婷" },
{ "id": 4, "supplier_id": 2, "name": "赵长青" }
]
}
数据表创建
使用以下命令创建数据表:
bash
yao migrate
关联关系声明详解
关联关系通过模型定义中的 relations
对象声明,支持多个映射关系。
关联关系对象字段说明
字段 | 类型 | 必填 | 说明 |
---|---|---|---|
name | string | 是 | 关联名称,查询时的引用标识符 |
type | string | 是 | 关系类型:hasOne (一对一) 或 hasMany (一对多) |
model | string | 是 | 关联模型名称 |
key | string | 是 | 关联模型中用于关联的字段名称 |
foreign | string | 是 | 当前模型中用于关联的字段名称 |
query | object | 否 | 关联模型的默认查询条件,可在实际查询时重载 |
hasOne 关联使用示例
hasOne 表示"拥有一个"关系,如用户拥有一个供应商的关联。
基本查询
查询用户并同时获取供应商信息:
bash
# 查询ID为1的用户及其供应商信息
yao run models.user.Find 1 '::{"withs":{ "supplier": {} }}'
# 查询所有用户及其供应商信息
yao run models.user.Get '::{"withs":{ "supplier": {} }}'
指定关联字段
bash
# 仅查询供应商的name字段
yao run models.user.Find 1 '::{"withs":{ "supplier": {"query":{ "select":["name"] }} }}'
按关联字段条件筛选
bash
# 查询供应商名称为"Yao App Engine"的用户
yao run models.user.Get '::{"withs":{ "supplier": {} }, "wheres":[{"rel":"supplier", "column":"name", "value":"Yao App Engine" }]}'
JavaScript中使用关联查询
javascript
function test() {
var user = Process('models.user.get', {
withs: {
supplier: {
// 关联供应商表
query: {
select: ['name', 'id'] // 指定查询字段
}
}
},
wheres: [{ column: 'supplier_id', value: 1, op: '=' }], // 查询条件
orders: [{ column: 'id', option: 'desc' }], // 排序条件
limit: 1 // 限制返回条数
});
}
hasMany 关联使用示例
hasMany 表示"拥有多个"关系,如供应商拥有多个用户的关联。
基本查询
bash
# 查询ID为1的供应商及其所有用户
yao run models.supplier.Find 1 '::{"withs":{ "users": {} }}'
# 查询所有供应商及其所有用户
yao run models.supplier.Get '::{"withs":{ "users": {} }}'
指定关联字段
bash
# 仅查询用户的name字段
yao run models.supplier.Find 1 '::{"withs":{ "users": { "query":{"select":["name"] }} }}'
关联数据筛选
bash
# 查询名为"张无忌"的用户所属的供应商
yao run models.supplier.Find 1 '::{"withs":{ "users": { "wheres":[{"column":"name", "value":"张无忌"}] } }}'
嵌套关联查询
关联关系支持嵌套查询,可以通过多层 withs
参数实现。
多层嵌套示例
bash
# 查询供应商及其用户,同时查询用户的供应商信息(形成循环引用)
yao run models.supplier.Find 1 '::{"withs":{ "users": { "withs": {"supplier":{} } } }}'
# 查询所有供应商的嵌套数据
yao run models.supplier.Get '::{"withs":{ "users": { "withs": {"supplier":{} } } }}'
注意事项
- 嵌套查询可能导致数据量过大,请谨慎使用深层嵌套
- 关联查询会增加数据库负担,请只查询必要字段
- 复杂的关联查询建议在后端处理而非直接通过API查询
通过合理使用数据模型关联,可以大幅简化数据查询逻辑,提高开发效率。