数据模型-关联关系
[TOC]
什么是关联关系
关联关系是指不同数据实体之间的连接方式,描述了数据如何相互关联。在数据库设计和编程中,主要有三种基本关联关系:
三种基本关联关系及解决方案
- 一对多关系(1:N) 通俗解释:一个"主"实体可以对应多个"从"实体,但一个"从"实体只能对应一个"主"实体。
例子:
一个部门有多个员工,但一个员工只能属于一个部门 一个用户可以发表多篇文章,但一篇文章只能由一个用户发表
解决方案:
在"多"的一方(员工表/文章表)添加外键指向"一"的一方(部门表/用户表) 例如员工表中有department_id字段指向部门表的ID
- 多对一关系(N:1)
说明:这实际上是一对多关系的反向视角,解决方案与一对多相同。
- 多对多关系(M:N) 通俗解释:两个实体可以相互拥有多个关联。
例子:
学生和课程:一个学生可以选修多门课程,一门课程可以有多个学生 用户和角色:一个用户可以有多个角色,一个角色可以分配给多个用户
解决方案:
使用中间表/关联表(junction table)来存储两个实体的关联关系 中间表通常只包含两个外键,分别指向两个关联表的主键 例如:学生课程关联表包含student_id和course_id两个字段
数据模型中的关联关系
学生模型:
教师模型:
选课模型:
多对一和一对多
以学生表和教师表为例。
学生表要通过关联关系teacher_id与教师表进行关联
则学生模型需要建立多对一关联关系到教师模型,建立关联老师
。在教师模型,则会被动出现一对多关联:管理的学生列表
。
多对多
以学生表和选课表为例。
学生表需要一个中间表来关联教师表。
学生模型需要建立多对多关联关系到选课模型,建立选课列表
。在选课模型,则会被动出现多对多关联:学生列表
。
查询关联关系
携带关联表
仅需要额外指定关联关系字段即可。需要使用到关键字:select
。
APIs示例
module.exports = async function (params, context) {
const result = await context.callModel({
dataSourceName: 'student', // 数据模型标识,可以前往「数据源 - 数据模型」列表页查看
methodName: 'wedaGetRecordsV2', // 数据模型方法标识,支持的方法可以前往「数据源 - 数据模型」的任一数据模型详情页查看当前模型支持的方法
params: {
select : {
"$master" : true, "teacher_id" : true
},
getCount : true,
pageSize : 10,
pageNumber : 1
}, // 数据模型方法的入参
});
// 在这里返回这个方法的结果,需要与出参定义的结构映射
return result;
};
查看结果
{
"total":3,
"records":[
{
"owner":"1871099876542291970",
"createdAt":1748340164367,
"createBy":"1871099876542291970",
"updateBy":"1871099876542291970",
"_openid":"1871099876542291970",
"name":"Student Zhang",
"_id":"BH4UMKTNM6",
"age":18,
"updatedAt":1748340164367,
},
{
"owner":"1871099876542291970",
"createdAt":1747299013876,
"createBy":"1871099876542291970",
"updateBy":"1871099876542291970",
"teacher_id": {
"owner":"1871099876542291970",
"createdAt":1747298935881,
"createBy":"1871099876542291970",
"updateBy":"1871099876542291970",
"_openid":"1871099876542291970",
"name":"zhang",
"_id":"BERMUX1E6L",
"updatedAt":1748341135384,
},
"_openid":"1871099876542291970",
"name":"zhang2",
"_id":"BERN1Y59JG",
"age":33,
"updatedAt":1747299013876,
},
{
"owner":"1871099876542291970",
"createdAt":1747298998990,
"createBy":"1871099876542291970",
"updateBy":"1871099876542291970",
"teacher_id": {
"owner":"1871099876542291970",
"createdAt":1747298935881,
"createBy":"1871099876542291970",
"updateBy":"1871099876542291970",
"_openid":"1871099876542291970",
"name":"zhang",
"_id":"BERMUX1E6L",
"updatedAt":1748341135384,
},
"_openid":"1871099876542291970",
"name":"foo",
"_id":"BERN0LHV2Y",
"age":12,
"updatedAt":1748340983535,
},
],
}
可视化开发编辑器示例
请求
async ({ params }) => {
const data = await $w.cloud.callDataSource({
dataSourceName: 'student', // 数据模型标识,可以前往「数据源 - 数据模型」列表页查看
methodName: 'wedaGetRecordsV2', // 数据模型方法标识,支持的方法可以前往「数据源 - 数据模型」的任一数据模型详情页查看当前模型支持的方法
params: {
select : {
"$master" : true, "teacher_id" : true
},
getCount : true,
pageSize : 10,
pageNumber : 1
}, // 数据模型方法的入参
});
console.log("请求结果", data);
return data;
}
查看结果
{
"records": [
{
"owner": "1871099876542291970",
"createdAt": 1748340164367,
"createBy": "1871099876542291970",
"updateBy": "1871099876542291970",
"_openid": "1871099876542291970",
"name": "Student Zhang",
"_id": "BH4UMKTNM6",
"age": 18,
"updatedAt": 1748340164367
},
{
"owner": "1871099876542291970",
"teacher_id": {
"owner": "1871099876542291970",
"createdAt": 1747298935881,
"createBy": "1871099876542291970",
"updateBy": "1871099876542291970",
"_openid": "1871099876542291970",
"name": "zhang",
"_id": "BERMUX1E6L",
"updatedAt": 1748341135384
},
"createdAt": 1747299013876,
"createBy": "1871099876542291970",
"updateBy": "1871099876542291970",
"_openid": "1871099876542291970",
"name": "zhang2",
"_id": "BERN1Y59JG",
"age": 33,
"updatedAt": 1747299013876
},
{
"owner": "1871099876542291970",
"teacher_id": {
"owner": "1871099876542291970",
"createdAt": 1747298935881,
"createBy": "1871099876542291970",
"updateBy": "1871099876542291970",
"_openid": "1871099876542291970",
"name": "zhang",
"_id": "BERMUX1E6L",
"updatedAt": 1748341135384
},
"createdAt": 1747298998990,
"createBy": "1871099876542291970",
"updateBy": "1871099876542291970",
"_openid": "1871099876542291970",
"name": "foo",
"_id": "BERN0LHV2Y",
"age": 12,
"updatedAt": 1748340983535
}
],
"total": 3,
"profile": {
"requestTimeCost": 1042,
"trrigerTimeCost": 1043,
"resolveParamsTimecost": 1
}
}
携带关联表-旧关联关系或者系统字段
系统字段均为旧关联关系。 在指定额外字段的基础上,要增加旧关联关系的开关。 注意:关联的系统字段如果想要查询数据。 需要切换到正式环境。 体验环境不存在系统字段数据。
APIs示例
这里以owner为例。
module.exports = async function (params, context) {
const result = await context.callModel({
dataSourceName: 'student', // 数据模型标识,可以前往「数据源 - 数据模型」列表页查看
methodName: 'wedaGetRecordsV2', // 数据模型方法标识,支持的方法可以前往「数据源 - 数据模型」的任一数据模型详情页查看当前模型支持的方法
params: {
select : {
"$master" : true, "owner" : true,
},
compatibleWithV1:true,
getCount : true,
pageSize : 10,
pageNumber : 1
}, // 数据模型方法的入参
});
// 在这里返回这个方法的结果,需要与出参定义的结构映射
return result;
};
查看结果
{
"records": [
{
"createdAt": 1748402459055,
"updateBy": "1871099876542291970",
"updatedAt": 1748402459055,
"owner": "1871099876542291970",
"createBy": "1871099876542291970",
"_openid": "1871099876542291970",
"name": "luke",
"_id": "BH9PTF6U9W",
"age": 24,
"@owner": {
"v1": {
"primaryColumn": "name",
"record": {
"parent_user_id": "",
"source": 1,
"type": 0,
"uuid": "1871099876542291970",
"user_desc": "超级管理员用户",
"createdAt": 1734939948634,
"createBy": "administrator",
"env_id": "lowcode-7gc7c86g01c220de",
"updateBy": "administrator",
"name": "administrator",
"internal_user_type": 1,
"uin": "100021405902",
"_id": "1871099876542291970",
"sub_uin": "100021405902",
"updatedAt": 1734939948634
}
}
}
}
],
"total": 1
}
可视化开发编辑器示例
请求
async ({ params }) => {
const data = await $w.cloud.callDataSource({
dataSourceName: 'student', // 数据模型标识,可以前往「数据源 - 数据模型」列表页查看
methodName: 'wedaGetRecordsV2', // 数据模型方法标识,支持的方法可以前往「数据源 - 数据模型」的任一数据模型详情页查看当前模型支持的方法
params: {
select : {
"$master" : true, "owner" : true,
},
compatibleWithV1:true,
getCount : true,
pageSize : 10,
pageNumber : 1
}, // 数据模型方法的入参
});
console.log("请求结果", data);
return data;
}
查看结果
{
"records": [
{
"createdAt": 1748402459055,
"updateBy": "1871099876542291970",
"updatedAt": 1748402459055,
"owner": "1871099876542291970",
"createBy": "1871099876542291970",
"_openid": "1871099876542291970",
"name": "luke",
"_id": "BH9PTF6U9W",
"age": 24,
"@owner": {
"v1": {
"primaryColumn": "name",
"record": {
"parent_user_id": "",
"source": 1,
"type": 0,
"uuid": "1871099876542291970",
"user_desc": "超级管理员用户",
"createdAt": 1734939948634,
"createBy": "administrator",
"env_id": "lowcode-7gc7c86g01c220de",
"updateBy": "administrator",
"name": "administrator",
"internal_user_type": 1,
"uin": "100021405902",
"_id": "1871099876542291970",
"sub_uin": "100021405902",
"updatedAt": 1734939948634
}
}
}
}
],
"total": 1,
"profile": {
"requestTimeCost": 185,
"trrigerTimeCost": 185,
"resolveParamsTimecost": 0
}
}
使用关联查询-查询多对一
使用关联查询需要用到关键字:relateWhere
。
这里的查询结果是关联老师的姓名=li的学生信息。同时携带关联老师信息。
APIs示例
module.exports = async function (params, context) {
const result = await context.callModel({
dataSourceName: 'student', // 数据模型标识,可以前往「数据源 - 数据模型」列表页查看
methodName: 'wedaGetRecordsV2', // 数据模型方法标识,支持的方法可以前往「数据源 - 数据模型」的任一数据模型详情页查看当前模型支持的方法
params: {
select : {
"$master" : true, "teacher_id" : true
},
filter:{relateWhere:{
teacher_id:{
where:{name:{
$eq: "li"
}
}}
}
},
getCount : true,
pageSize : 3,
pageNumber : 1
}, // 数据模型方法的入参
});
// 在这里返回这个方法的结果,需要与出参定义的结构映射
return result;
};
查看结果
{
"total":1,
"records":[
{
"owner":"1871099876542291970",
"createdAt":1747299013876,
"createBy":"1871099876542291970",
"updateBy":"1871099876542291970",
"teacher_id": {
"owner":"1871099876542291970",
"createdAt":1747298939873,
"createBy":"1871099876542291970",
"updateBy":"1871099876542291970",
"_openid":"1871099876542291970",
"name":"li",
"_id":"BERMV99BBN",
"updatedAt":1747298939873,
},
"_openid":"1871099876542291970",
"name":"zhang2",
"_id":"BERN1Y59JG",
"age":33,
"updatedAt":1748403261024,
},
],
}
可视化开发编辑器示例
请求
async ({ params }) => {
const data = await $w.cloud.callDataSource({
dataSourceName: 'student', // 数据模型标识,可以前往「数据源 - 数据模型」列表页查看
methodName: 'wedaGetRecordsV2', // 数据模型方法标识,支持的方法可以前往「数据源 - 数据模型」的任一数据模型详情页查看当前模型支持的方法
params: {
select : {
"$master" : true, "teacher_id" : true
},
filter:{relateWhere:{
teacher_id:{
where:{name:{
$eq: "li"
}
}}
}
},
getCount : true,
pageSize : 3,
pageNumber : 1
}, // 数据模型方法的入参
});
console.log("请求结果", data);
return data;
}
查看结果
{
"records": [
{
"owner": "1871099876542291970",
"teacher_id": {
"owner": "1871099876542291970",
"createdAt": 1747298939873,
"createBy": "1871099876542291970",
"updateBy": "1871099876542291970",
"_openid": "1871099876542291970",
"name": "li",
"_id": "BERMV99BBN",
"updatedAt": 1747298939873
},
"createdAt": 1747299013876,
"createBy": "1871099876542291970",
"updateBy": "1871099876542291970",
"_openid": "1871099876542291970",
"name": "zhang2",
"_id": "BERN1Y59JG",
"age": 33,
"updatedAt": 1748403261024
}
],
"total": 1,
"profile": {
"requestTimeCost": 203,
"trrigerTimeCost": 203,
"resolveParamsTimecost": 0
}
}
使用关联查询-查询一对多
使用关联查询需要用到relateWhere
关键字。
查询关联学生中,有符合条件的老师信息。
APIs示例
module.exports = async function (params, context) {
const result = await context.callModel({
dataSourceName: 'teacher', // 数据模型标识,可以前往「数据源 - 数据模型」列表页查看
methodName: 'wedaGetRecordsV2', // 数据模型方法标识,支持的方法可以前往「数据源 - 数据模型」的任一数据模型详情页查看当前模型支持的方法
params: {
select : {
"$master" : true, "student_list" : true
},
filter:{relateWhere:{
student_list:{
where:{name:{
$eq: "zhang2"
}
}}
}
},
getCount : true,
pageSize : 3,
pageNumber : 1
}, // 数据模型方法的入参
});
// 在这里返回这个方法的结果,需要与出参定义的结构映射
return result;
};
查看结果
{
"total":1,
"records":[
{
"owner":"1871099876542291970",
"createdAt":1747298939873,
"createBy":"1871099876542291970",
"updateBy":"1871099876542291970",
"_openid":"1871099876542291970",
"name":"li",
"_id":"BERMV99BBN",
"student_list":[
{
"owner":"1871099876542291970",
"createdAt":1747299013876,
"createBy":"1871099876542291970",
"updateBy":"1871099876542291970",
"_openid":"1871099876542291970",
"name":"zhang2",
"_id":"BERN1Y59JG",
"age":33,
"updatedAt":1748403261024,
},
],
"updatedAt":1747298939873,
},
],
}
可视化开发编辑器示例
请求
async ({ params }) => {
const data = await $w.cloud.callDataSource({
dataSourceName: 'student', // 数据模型标识,可以前往「数据源 - 数据模型」列表页查看
methodName: 'wedaGetRecordsV2', // 数据模型方法标识,支持的方法可以前往「数据源 - 数据模型」的任一数据模型详情页查看当前模型支持的方法
params: {
select : {
"$master" : true, "student_list" : true
},
filter:{relateWhere:{
student_list:{
where:{name:{
$eq: "zhang2"
}
}}
}
},
getCount : true,
pageSize : 3,
pageNumber : 1
}, // 数据模型方法的入参
});
console.log("请求结果", data);
return data;
}
查看结果
{
"records": [
{
"owner": "1871099876542291970",
"createdAt": 1748340164367,
"createBy": "1871099876542291970",
"updateBy": "1871099876542291970",
"_openid": "1871099876542291970",
"name": "Student Zhang",
"_id": "BH4UMKTNM6",
"age": 18,
"updatedAt": 1748412619234
},
{
"owner": "1871099876542291970",
"createdAt": 1747299013876,
"createBy": "1871099876542291970",
"updateBy": "1871099876542291970",
"_openid": "1871099876542291970",
"name": "zhang2",
"_id": "BERN1Y59JG",
"age": 33,
"updatedAt": 1748403261024
},
{
"owner": "1871099876542291970",
"createdAt": 1747298998990,
"createBy": "1871099876542291970",
"updateBy": "1871099876542291970",
"_openid": "1871099876542291970",
"name": "foo",
"_id": "BERN0LHV2Y",
"age": 12,
"updatedAt": 1748340983535
}
],
"total": 3,
"profile": {
"requestTimeCost": 838,
"trrigerTimeCost": 838,
"resolveParamsTimecost": 0
}
}
使用关联查询-查询多对多
使用关联查询需要用到relateWhere
关键字。
查询关联选课中,有符合条件的学生信息。 比如,选择了语文课程的学生。
APIs示例
module.exports = async function (params, context) {
const result = await context.callModel({
dataSourceName: 'student', // 数据模型标识,可以前往「数据源 - 数据模型」列表页查看
methodName: 'wedaGetRecordsV2', // 数据模型方法标识,支持的方法可以前往「数据源 - 数据模型」的任一数据模型详情页查看当前模型支持的方法
params: {
select : {
"$master" : true, "course_id_list" : true
},
filter:{relateWhere:{
course_id_list:{
where:{name:{
$eq: "语文"
}
}}
}
},
getCount : true,
pageSize : 10,
pageNumber : 1
}, // 数据模型方法的入参
});
// 在这里返回这个方法的结果,需要与出参定义的结构映射
return result;
};
查看结果
{
"total":1,
"records":[
{
"owner":"1871099876542291970",
"createdAt":1748340164367,
"createBy":"1871099876542291970",
"course_id_list":[
{
"owner":"1871099876542291970",
"schedule":[1,2,3],
"createdAt":1748333699720,
"createBy":"1871099876542291970",
"updateBy":"1871099876542291970",
"_openid":"1871099876542291970",
"name":"语文",
"_id":"BH4BGT241E",
"course_hour":30,
"updatedAt":1748333699720,
},
],
"updateBy":"1871099876542291970",
"_openid":"1871099876542291970",
"name":"Student Zhang",
"_id":"BH4UMKTNM6",
"age":18,
"updatedAt":1748412619234,
},
],
}
可视化开发编辑器示例
请求
async ({ params }) => {
const data = await $w.cloud.callDataSource({
dataSourceName: 'student', // 数据模型标识,可以前往「数据源 - 数据模型」列表页查看
methodName: 'wedaGetRecordsV2', // 数据模型方法标识,支持的方法可以前往「数据源 - 数据模型」的任一数据模型详情页查看当前模型支持的方法
params: {
select : {
"$master" : true, "course_id_list" : true
},
filter:{relateWhere:{
course_id_list:{
where:{name:{
$eq: "语文"
}
}}
}
},
getCount : true,
pageSize : 10,
pageNumber : 1
}, // 数据模型方法的入参
});
console.log("请求结果", data);
return data;
}
查看结果
{
"records": [
{
"owner": "1871099876542291970",
"createdAt": 1748340164367,
"createBy": "1871099876542291970",
"updateBy": "1871099876542291970",
"_openid": "1871099876542291970",
"name": "Student Zhang",
"_id": "BH4UMKTNM6",
"age": 18,
"updatedAt": 1748412619234
},
{
"owner": "1871099876542291970",
"createdAt": 1747299013876,
"createBy": "1871099876542291970",
"updateBy": "1871099876542291970",
"_openid": "1871099876542291970",
"name": "zhang2",
"_id": "BERN1Y59JG",
"age": 33,
"updatedAt": 1748403261024
},
{
"owner": "1871099876542291970",
"createdAt": 1747298998990,
"createBy": "1871099876542291970",
"updateBy": "1871099876542291970",
"_openid": "1871099876542291970",
"name": "foo",
"_id": "BERN0LHV2Y",
"age": 12,
"updatedAt": 1748340983535
}
],
"total": 3,
"profile": {
"requestTimeCost": 549,
"trrigerTimeCost": 549,
"resolveParamsTimecost": 0
}
}