第6章 数据库设计与建模_第1页
第6章 数据库设计与建模_第2页
第6章 数据库设计与建模_第3页
第6章 数据库设计与建模_第4页
第6章 数据库设计与建模_第5页
已阅读5页,还剩15页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

《微信小程序电商实战(前后端分离架构)》第6章数据库设计与建模本章目录01.数据库设计概述基本概念与设计步骤解析02.电商系统ER图绘制梳理业务数据逻辑关系03.核心数据模型定义数据表结构与字段设计04.模型关系与关联设计外键约束与关联查询优化05.测试数据初始化编写脚本填充模拟数据DATABASEDESIGNE-COMMERCESYSTEM为何数据库设计如此重要?数据基石数据库是应用程序的核心,存储所有业务数据。其设计直接决定了系统的稳定性和可靠性,是业务运行的根本保障。性能关键合理的表结构、索引设计和数据关联方式,能够显著提升数据的读写性能,避免系统出现性能瓶颈,保障流畅体验。维护成本良好的设计能降低数据冗余,保证数据的一致性和完整性,大幅减少后期的维护难度与成本,提高开发效率。业务支撑数据库模型直接反映业务逻辑,得当的设计能更好地支撑业务需求,并为未来的业务扩展提供灵活性与扩展性。数据库设计概述核心设计步骤需求分析深入理解业务需求,明确数据存储内容及关系。概念结构设计绘制ER图建立概念模型,不涉及具体数据库实现。逻辑结构设计转换为具体表结构,定义字段、类型和约束。物理结构设计针对DBMS设计存储结构、索引及分区等物理细节。关键设计原则原子性:字段是不可再分的最小数据单元。一致性:保证数据在不同表中存储一致,避免矛盾。完整性:通过主键外键约束确保数据准确可靠。安全性:设计合理权限体系,保护数据不被非法访问。可扩展性:模型应适应未来业务变化和增长。电商系统ER图绘制ER图(实体关系图)是数据库概念设计的核心工具。左侧图表直观展示了电商系统中各核心模块的数据关联结构,为后续逻辑设计奠定基础。核心实体(CoreEntities)用户(User)

系统使用者,含基本信息商品(Product)

名称、价格、库存信息订单(Order)

购买凭证与状态记录购物车(Cart)

暂存待购商品主要关系(Relationships)用户1:N订单:单用户可拥有多订单,订单归属于唯一用户订单1:N订单项:订单包含多个商品项,项属于唯一订单商品N:1分类:多商品可同属一类,分类包含多商品用户N:N商品:通过收藏关系,用户可收藏多商品,商品可被多用户收藏核心数据模型定义-用户表(users)字段名类型描述约束_idObjectId用户ID主键,由MongoDB自动生成,唯一标识一个用户。openidString微信唯一标识唯一,非空。用于与微信用户关联,是用户认证的关键。nameString用户昵称可空。用户可以选择是否填写。avatarString用户头像URL可空。存储用户头像的网络地址。phoneString手机号码可空,唯一。用于联系用户,需要保证唯一性。createdAtDate创建时间自动生成。记录用户首次注册的时间。updatedAtDate更新时间自动生成。记录用户信息最后一次更新的时间。核心数据模型定义-商品表(products)字段名类型描述约束_idObjectId商品ID主键,自动生成。nameString商品名称非空。商品的标题。descriptionString商品描述可空。商品的详细介绍,可以是富文本。priceNumber商品价格非空,默认0。商品的销售价格。stockNumber商品库存非空,默认0。库存数量,用于管理。categoryIdObjectId分类ID非空,外键。关联分类表的`_id`。imagesArray商品图片URL数组可空。存储商品的多张图片地址。salesNumber销量非空,默认0。记录销售数量。isOnSaleBoolean是否上架非空,默认true。标识是否在售。createdAtDate创建时间自动生成。updatedAtDate更新时间自动生成。核心数据模型定义-分类表(categories)字段名类型描述约束_idObjectId分类ID,系统自动生成唯一标识。主键,自动生成。nameString分类名称,如“手机”、“电脑”。非空。parentIdObjectId父分类ID,用于实现多级分类,根分类为null。可空,外键,自引用。levelNumber分类级别,标识层级深度,根分类为1级。非空,默认1。sortNumber排序字段,用于控制分类在前端展示的顺序。非空,默认0。createdAtDate记录创建时间。自动生成。updatedAtDate记录最后更新时间。自动生成。核心数据模型定义-订单表(orders)字段名类型描述约束_idObjectId订单ID主键,自动生成。orderNoString订单编号(用户可见,含时间戳和随机数)唯一,非空。userIdObjectId用户ID(关联用户表)非空,外键。addressIdObjectId地址ID(关联地址表,记录收货地址)非空,外键。totalPriceNumber订单总价(所有商品总金额)非空,默认0。statusString订单状态:pending/paid/shipped/completed/cancelled非空,默认'pending'。paymentTypeString支付方式:wechat/alipay等可空。paymentTimeDate记录用户的支付时间可空。shippingTimeDate记录商家的发货时间可空。receiveTimeDate记录用户的确认收货时间可空。remarkString用户在下单时填写的备注信息可空。createdAtDate创建时间自动生成。updatedAtDate更新时间自动生成。核心数据模型定义-订单项表(orderItems)字段名类型描述约束_idObjectId订单项ID主键,自动生成。orderIdObjectId订单ID非空,外键。关联到订单表的`_id`。productIdObjectId商品ID非空,外键。关联到商品表的`_id`。productNameString商品名称非空。记录下单时商品名称,用于订单快照。productImageString商品图片URL可空。记录下单时商品图片,用于订单快照。priceNumber商品单价非空,默认0。记录下单时商品的单价。quantityNumber购买数量非空,默认1。用户购买该商品的数量。createdAtDate创建时间自动生成。updatedAtDate更新时间自动生成。模型关系与关联设计(Mongoose)1.引用关联定义(Schema)constproductSchema=newmongoose.Schema({name:{type:String,required:true},categoryId:{type:Schema.Types.ObjectId,ref:'Category',//关联模型required:true}},{timestamps:true});2.关联查询(Query)constproducts=awaitProduct.find({isOnSale:true}).populate('categoryId','name')//加载关联数据.sort({sales:-1});//返回包含分类名称的商品列表核心要点:通过ref属性指定关联模型,利用populate方法在查询时自动加载关联数据,实现类似关系型数据库的外键关联效果。模型关系与关联设计-嵌入文档核心概念(EmbeddedDocument)将一个文档直接嵌入到另一个文档中作为字段值,形成“包含”关系。适用场景实体间是“包含”关系,子文档仅属于一个父文档子文档数据量小且不常更新,查询时需同时获取父子信息优缺点分析优点:查询速度快,一次查询即可获取完整数据。缺点:数据冗余,更新子文档时需同步更新所有父文档。示例:订单与收货地址constmongoose=require('mongoose');constaddressSchema=newmongoose.Schema({name:{type:String,required:true},phone:{type:String,required:true},detail:{type:String,required:true}});constorderSchema=newmongoose.Schema({orderNo:{type:String,unique:true},//直接嵌入地址子文档,而非引用IDaddress:{type:addressSchema,required:true},totalPrice:{type:Number}});总结:嵌入文档适合“包含”关系且数据相对稳定的场景,以空间换时间,提升查询效率。引用关联(Reference)vs嵌入文档(Embedded)特性维度引用关联(Reference)嵌入文档(Embedded)数据存储数据分散在不同集合,通过ID引用关联。子文档直接嵌入父文档,数据集中存储。查询性能需关联查询(如populate),层级多时性能较低。一次查询即获全部信息,速度快,无需关联。数据一致性易于维护,更新一处即可同步所有引用。存在冗余,需更新所有副本,否则易不一致。适用场景一对多关系,子文档被多父文档引用数据量大,需独立扩展和查询一对一或包含关系,子文档仅属一个父文档数据量小且不常更新,需频繁一起查询典型示例用户与订单、商品与分类、订单与订单项订单与收货地址、文章与小型评论、个人资料详情关键决策:数据复用选引用,性能优先且私有用嵌入测试数据初始化src/scripts/initData.js(核心逻辑)constmongoose=require('mongoose');constconnectDB=require('../utils/db');constCategory=require('../models/category.model');//1.连接数据库并清空旧数据connectDB();Category.deleteMany({});//2.定义测试数据(分类/商品)constcategories=[{name:'电子产品',...}];//3.批量插入数据并关联IDCategory.insertMany(categories);运行脚本nodesrc/scripts/initData.js核心作用自动连接数据库并清空旧数据批量插入预设的分类与商品数据快速构建开发与测试环境通过脚本化初始化,告别手动录入,提升研发效率与数据一致性实战案例-数据库操作示例示例1:查询商品列表并关联分类信息//获取热销商品列表(关联分类)exports.getHotProducts=async(limit=10)=>{constproducts=awaitProduct.find({isOnSale:true}).populate('categoryId','name')//关联分类.sort({sales:-1})//销量降序.limit(limit);returnproducts;};示例2:创建订单并插入订单项(事务)//开启事务保证数据一致性constsession=awaitmongoose.startSession();session.startTransaction();//1.创建订单&2.检查并扣减库存product.stock-=item.quantity;//预减库存awaitproduct.save({session});//3.插入订单项&提交事务awaitsession.commitTransaction();核心技术点:事务一致性保障使用Mongoose的Transaction机制,确保订单创建、库存扣减等操作要么全部成功,要么全部失败,避免数据不一致。常见问题排查-数据关联查询失败问题现象:使用populate进行关联查询时,关联字段为null,或者没有返回预期的关联数据。1.检查引用ID的有效性确认存储的引用ID是有效的ObjectId,且在被引用集合中存在对应文档。2.检查模型定义中的ref属性ref属性值必须与被引用模型名称完全一致(区分大小写)。3.检查populate的语法确认传入的字段名与主模型定义的引用字段名完全一致。4.检查查询条件确认查询条件是否正确,是否过滤掉了需要关联的数据。5.使用lean()方法若无需Mongoose操作,可在populate后使用lean()转换为普通JS对象,解决潜在关联问题。常见问题排查-性能问题问题现象:查询速度慢,系统响应延迟,特别是在数据量较大时表现尤为明显。添加合适的索引为高频查询、排序、关联字段建立索引。示例:为商品的name、categoryId等字段添加索引以加速检索。优化查询语句使用select仅查询所需字段,避免大字段;利用limit/skip实现分页;严禁在循环中执行数据库操作。使用聚合查询对于复杂统计和数据分析,使用MongoDB聚合管道(AggregationPipeline)替代多次查询,提升处理效率。数据冗余与缓存策略适度使用数据冗余减少关联查询;引入Redis缓存热点数据,大幅减轻数据库压力,提升响应速度。本章

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论