平台已创建好5个供用户直接使用的业务表
{
id: bigint,
auth: bigint, // 创建该记录的用户ID
type: text, // 类型,方便分类及搜索
name: text, // 唯一名,有时用来代替ID更容易理解与记忆
x: {},
y: {}
}我们通常把具体的、能喊得上名字的数据存放在产品表中,不管是有形的实体物品还是无形的虚拟产品
{
id: bigint,
type: text, // 类型,直观表达此数据是什么东西
key: text, // 关键信息,确保同type的组合是唯一的
x: {},
y: {}
}由type和key两个字段组成联合主键,不能归到其它表的才存入此表。
很多时候key是另一条数据的id,表示它是那一条数据相关联的子表数据/附属信息。
{
id: bigint,
phone: text, // 手机号码,登录用
mail: text, // 邮件地址,登录用
role: [], // 角色,控制权限用
wx: {}, // 微信账号信息
x: {},
y: {}
}{
id: bigint,
auth: bigint, // 创建该记录的用户ID
type: text, // 订单分类
note: text, // 订单描述
total: numeric, // 付款总金额
refund: numeric, // 退款金额
x: {},
y: {},
z: {} // 支付信息,由平台维护
}注意:totol和refund的存储类型是numeric,为保持数值精度其返回前端的类型是字符串。如需要计算可考虑转换成浮点型:parseFloat(totol)。
{
id: bigint,
auth: bigint, // 创建该记录时用户ID
type: text, // 类型,i是image, v是video, f是file
url: text, // 资源在对象存储服务器的地址,虚拟字段,并不真实存在
name: text, // 文件名
ext: text, // 文件后缀/扩展名
size: integer, // 文件大小(K)
del: timestamp, // 删除时间戳
v: {}, // 每日访问次数统计
x: {},
y: {}
}存放用户上传的图片/视频/文件信息,此表在用户上传资源时由平台自动创建。
每个表都有一个由平台统一生成的主键id;它由16位数字组成,可以用isId()来判断参数是否是有效ID。
它前10位是该记录的创建时间(精确到秒),可以用date()把id转换成时间。还可以用id()通过一个时间参数来构建一个id并以此来查询数据库。
除了用户表都有一个必填的类型type字段,用来对数据进行分类,每种分类都可以认为是独立的数据表。
type/name/key应避免使用特殊字符,如空格})*'",:@%$。
每个表都有json类型的x和y字段。x存放具体的业务数据,通常把整个x放入表单给用户编辑并整体保存回数据库。而作为附加数据的y存放不让用户直接修改/不常变动的信息,比如审批信息。
在后端执行的表达式中,如果要访问x字段里面的属性,需要使用x.前缀;
在前端,平台为了方便会把x字段里面的属性复制一份到x字段外面,这样访问x字段里面的属性就可以直接访问而不需要使用x.前缀了。
x和y字段是可以嵌套数组的,可存放非常复杂的数据,传统子表里的数据都可以一起塞到里面。那到底是分母子表存储还是嵌套存储呢?
通常无需单独拎出来查询的、信息量少的、记录条数有限的数据适合嵌套,否则就应该分开存储。
比如简历中的工作经历列表就可以嵌套,因为一个人的工作经历数量有限、不会出现单独查工作经历而不查人的情况。再比如会计凭证中的分录也可以嵌套,每个凭证都有至少一个借和一个贷分录,但总量不会太多。
而一个用户发布的文章就不应该嵌套的用户表中,一篇文章的评论也不应该嵌套的文章表里,因为文章/评论需要单独查询,而且它们的数量也难以估计。