记录一次云数据库设计的重构。
使用云开发之后,一个小程序可以快速的从无到有上线运行,这个速度是传统开发不能比的,特别适合初创团队快速上线产品抢占市场或试错。而使用云开发,我们通常要做的第一件事就是设计数据库,云开发的数据库使用结构化的文档来存储数据,不再是关系型数据库里每个行列交汇处都必须有且只有一个值,它可以是一个数组、一个对象,或者更加复杂的嵌套。
在初期产品需要快速出可用原型,上线时间紧迫的情况下,数据库设计难免会有欠考虑的地方,等产品开始进入迭代期就可能会有重构需求。这里用个人刚经历的一个项目案例来给需要数据库设计重构的朋友们一个参考。
这次数据库重构只有一个目的,把一个最初内嵌的字段提取出来,单独创建一个集合来管理。也就是把反范式化设计的数据库结构转成范式化的设计,这两种数据库设计有何区别可以看另一位云开发布道师东哥的文章,数据库的设计。
在产品上线的第一个版本时,bagList字段是内嵌在一个user文档里的,如下:
这里的数据是精简版,真实情况还会有很多商品信息、用户信息等,此处只是举例说明。
这样的反范式化设计在最初上线的版本中并没有什么问题,因为商品价格较高,早期也认为用户并不会大量购买。然而没想到的是,在经过一波运营宣传后,用户量开始猛增,其中也出现了一些土豪用户,他们的购买数量已经不是个位数了,有的都超过了100件以上,此时bagList字段的数组长度就变得非常大。在这个时候,数据分页、商品发货、修改商品信息就已经很难维护,一直使用了层层的聚合操作先查询出来,然后再修改。就在想着是否要重构数据结构的时候,新的开发需求来了,要让用户和用户之间可以互换商品,也正是这个需求让我决定了一定要重构数据库。
将bagList字段单独拿出来形成一个集合的好处有很多,数据分页很方便,修改商品信息很简单,且很多云数据库的原子操作修改都可以直接使用,更重要的是新需求互换功能只需要修改对应商品的所有者userid就可以完成。但此时内嵌结构已经使用了很久,数据也已经记录了很多,如何把这些历史数据无缝衔接的拿出来成了问题,这里使用了一系列的聚合操作来完成。
这里用的是云开发管理控制台自带的高级操作脚本,首先第一步开启聚合模式,在聚合中单次limit最大数现为10000,因改版时用户数正好低于10000,所以这里直接拉到最大。然后使用match来删选user集合中bagList字段不为空数组的文档。紧接着使用project选定在下一阶段想要的展示的字段,_id字段默认存在,其余字段直接舍弃。此时的执行结果如下图:
接下来我们就需要用unwind来拆分bagList,拆分完的数据结构如下:
此时每一个商品已经单独抽离出来,如果此时的结构已经达到了想要的要求,那就可以直接使用现有数据,如果还想自定义一下,那就可以继续使用聚合操作来完成,如上面我因为还有其他需求,使用聚合再次改变了一些结构写法,聚合的操作可以去云开发文档聚合学习。
聚合出来的数据并不是严格的json数据,现在的云开发控制台的高级脚本可以批量添加数据,add方法中的data可以为数组,这在数据量小的情况下可以直接使用,而我们这次聚合出来几千条数据,经测试,云开发的高级脚本并不支持那么大的数据量一次性导入,那么我们可以使用数据库的json格式导入。
创建一个新集合products,这里使用vscode把我们聚合出来的数据复制粘贴到一个名为products.json的新文件中(名称随意),然后将最外层的[]包裹删除,全局搜索 },换行{ 替换为 }换行{ ,把每条数据之间的逗号去除(注意:在搜索的时候,换行也要,不然内嵌数据的逗号也会被替换),保存并使用json方式把数据导入到products集合就大功告成啦。
因本人有此需求然而并没有找到相关资料,所以将自己摸索的方法和大家分享一下,如果有更好的无缝衔接的方法欢迎评论告知,谢谢~