434 lines
11 KiB
Markdown
434 lines
11 KiB
Markdown
# 实体关系设计
|
|
|
|
<cite>
|
|
**本文档引用的文件**
|
|
- [Brand.js](file://backend/src/models/Brand.js)
|
|
- [Model.js](file://backend/src/models/Model.js)
|
|
- [Ota.js](file://backend/src/models/Ota.js)
|
|
- [index.js](file://backend/src/models/index.js)
|
|
- [database.js](file://backend/src/config/database.js)
|
|
- [brands.js](file://backend/src/routes/brands.js)
|
|
- [models.js](file://backend/src/routes/models.js)
|
|
- [ota.js](file://backend/src/routes/ota.js)
|
|
- [app.js](file://backend/src/app.js)
|
|
- [index.js](file://backend/src/routes/index.js)
|
|
- [ota.js](file://backend/src/validators/ota.js)
|
|
</cite>
|
|
|
|
## 目录
|
|
1. [简介](#简介)
|
|
2. [项目结构](#项目结构)
|
|
3. [核心组件](#核心组件)
|
|
4. [架构概览](#架构概览)
|
|
5. [详细组件分析](#详细组件分析)
|
|
6. [依赖关系分析](#依赖关系分析)
|
|
7. [性能考虑](#性能考虑)
|
|
8. [故障排除指南](#故障排除指南)
|
|
9. [结论](#结论)
|
|
|
|
## 简介
|
|
|
|
本文件详细阐述了Audio Dashboard系统中Brand(品牌)、Model(型号)、Ota(OTA升级版本)三个核心实体之间的关系设计。该系统采用MySQL数据库和Sequelize ORM框架,实现了清晰的一对一和一对多关系映射,确保数据完整性和查询效率。
|
|
|
|
## 项目结构
|
|
|
|
系统采用典型的三层架构设计,重点关注数据模型层的设计和实现:
|
|
|
|
```mermaid
|
|
graph TB
|
|
subgraph "前端层"
|
|
FE[Vue.js 前端应用]
|
|
end
|
|
subgraph "后端层"
|
|
API[Express.js API服务]
|
|
ROUTES[路由层<br/>brands.js, models.js, ota.js]
|
|
MODELS[模型层<br/>Brand.js, Model.js, Ota.js]
|
|
VALIDATORS[验证器<br/>ota.js]
|
|
end
|
|
subgraph "数据层"
|
|
DB[(MySQL数据库)]
|
|
TABLES[表结构<br/>brand, model, ota]
|
|
end
|
|
FE --> API
|
|
API --> ROUTES
|
|
ROUTES --> MODELS
|
|
MODELS --> DB
|
|
DB --> TABLES
|
|
```
|
|
|
|
**图表来源**
|
|
- [app.js:1-60](file://backend/src/app.js#L1-L60)
|
|
- [index.js:1-13](file://backend/src/routes/index.js#L1-L13)
|
|
|
|
**章节来源**
|
|
- [app.js:1-60](file://backend/src/app.js#L1-L60)
|
|
- [index.js:1-13](file://backend/src/routes/index.js#L1-L13)
|
|
|
|
## 核心组件
|
|
|
|
### 数据库配置
|
|
|
|
系统使用Sequelize ORM进行数据库操作,配置特点如下:
|
|
|
|
- **数据库类型**: MySQL
|
|
- **字符集**: utf8mb4
|
|
- **时间戳**: 关闭自动时间戳管理
|
|
- **表名冻结**: 冻结表名,不使用复数形式
|
|
- **日志级别**: 开发环境启用SQL日志
|
|
|
|
**章节来源**
|
|
- [database.js:1-24](file://backend/src/config/database.js#L1-L24)
|
|
|
|
### 实体定义
|
|
|
|
#### Brand实体(品牌)
|
|
|
|
```mermaid
|
|
erDiagram
|
|
BRAND {
|
|
int id PK
|
|
varchar name UK
|
|
}
|
|
MODEL {
|
|
int id PK
|
|
varchar brand_name
|
|
varchar name
|
|
varchar form
|
|
varchar rig
|
|
varchar source
|
|
varchar eq_key
|
|
datetime create_at
|
|
}
|
|
OTA {
|
|
int id PK
|
|
int verCode
|
|
varchar verName
|
|
varchar url
|
|
varchar md5
|
|
smallint force
|
|
varchar desc
|
|
varchar model
|
|
int hw
|
|
smallint target
|
|
smallint beta
|
|
datetime startTime
|
|
datetime endTime
|
|
smallint status
|
|
datetime create_at
|
|
}
|
|
BRAND ||--o{ MODEL : "拥有"
|
|
MODEL ||--o{ OTA : "对应"
|
|
```
|
|
|
|
**图表来源**
|
|
- [Brand.js:1-23](file://backend/src/models/Brand.js#L1-L23)
|
|
- [Model.js:1-53](file://backend/src/models/Model.js#L1-L53)
|
|
- [Ota.js:1-97](file://backend/src/models/Ota.js#L1-L97)
|
|
|
|
#### Model实体(型号)
|
|
|
|
Model实体包含丰富的音频相关属性:
|
|
- **基础信息**: 品牌名称、型号名称、佩戴形式、阻抗
|
|
- **来源信息**: 数据来源标识
|
|
- **EQ缓存**: EQ键值用于缓存管理
|
|
- **时间戳**: 创建时间记录
|
|
|
|
#### Ota实体(OTA升级)
|
|
|
|
Ota实体设计用于管理设备固件升级:
|
|
- **版本控制**: 版本号(整数)、版本名称
|
|
- **文件管理**: 下载URL、MD5校验码
|
|
- **发布策略**: 强制升级、定向发布、灰度发布
|
|
- **时间窗口**: 生效时间和失效时间
|
|
- **状态管理**: 可用性状态
|
|
|
|
**章节来源**
|
|
- [Brand.js:1-23](file://backend/src/models/Brand.js#L1-L23)
|
|
- [Model.js:1-53](file://backend/src/models/Model.js#L1-L53)
|
|
- [Ota.js:1-97](file://backend/src/models/Ota.js#L1-L97)
|
|
|
|
## 架构概览
|
|
|
|
系统采用RESTful API设计模式,每个实体都有完整的CRUD操作:
|
|
|
|
```mermaid
|
|
sequenceDiagram
|
|
participant Client as 客户端
|
|
participant API as API网关
|
|
participant Route as 路由处理器
|
|
participant Model as Sequelize模型
|
|
participant DB as MySQL数据库
|
|
Client->>API : HTTP请求
|
|
API->>Route : 路由分发
|
|
Route->>Model : 数据库操作
|
|
Model->>DB : SQL执行
|
|
DB-->>Model : 查询结果
|
|
Model-->>Route : 数据对象
|
|
Route-->>API : 响应数据
|
|
API-->>Client : JSON响应
|
|
```
|
|
|
|
**图表来源**
|
|
- [brands.js:14-40](file://backend/src/routes/brands.js#L14-L40)
|
|
- [models.js:133-181](file://backend/src/routes/models.js#L133-L181)
|
|
- [ota.js:107-143](file://backend/src/routes/ota.js#L107-L143)
|
|
|
|
## 详细组件分析
|
|
|
|
### 关系映射策略
|
|
|
|
#### 当前实现状态
|
|
|
|
经过深入分析,发现当前代码库中**Brand与Model之间没有建立显式的Sequelize关联关系**。这种设计选择有其合理性:
|
|
|
|
1. **简化设计**: 避免复杂的外键约束
|
|
2. **灵活性**: 允许跨品牌的数据迁移
|
|
3. **性能考虑**: 减少JOIN操作的开销
|
|
|
|
#### 推荐的关系设计
|
|
|
|
基于业务需求,建议实现以下关系映射:
|
|
|
|
```mermaid
|
|
classDiagram
|
|
class Brand {
|
|
+int id
|
|
+string name
|
|
+hasMany(Model)
|
|
}
|
|
class Model {
|
|
+int id
|
|
+string brand_name
|
|
+string name
|
|
+string form
|
|
+string rig
|
|
+string source
|
|
+string eq_key
|
|
+datetime create_at
|
|
+belongsTo(Brand)
|
|
+hasMany(Ota)
|
|
}
|
|
class Ota {
|
|
+int id
|
|
+int verCode
|
|
+string verName
|
|
+string url
|
|
+string md5
|
|
+smallint force
|
|
+string desc
|
|
+string model
|
|
+int hw
|
|
+smallint target
|
|
+smallint beta
|
|
+datetime startTime
|
|
+datetime endTime
|
|
+smallint status
|
|
+datetime create_at
|
|
+belongsTo(Model)
|
|
}
|
|
Brand --> Model : "一对多"
|
|
Model --> Ota : "一对多"
|
|
```
|
|
|
|
**图表来源**
|
|
- [Brand.js:1-23](file://backend/src/models/Brand.js#L1-L23)
|
|
- [Model.js:1-53](file://backend/src/models/Model.js#L1-L53)
|
|
- [Ota.js:1-97](file://backend/src/models/Ota.js#L1-L97)
|
|
|
|
### 关系查询最佳实践
|
|
|
|
#### 基础查询模式
|
|
|
|
```mermaid
|
|
flowchart TD
|
|
Start([查询开始]) --> CheckType{"查询类型"}
|
|
CheckType --> |单表查询| DirectQuery["直接查询表"]
|
|
CheckType --> |关联查询| BuildJoin["构建JOIN语句"]
|
|
CheckType --> |聚合查询| AggQuery["使用聚合函数"]
|
|
DirectQuery --> Limit["限制结果数量"]
|
|
BuildJoin --> SelectCols["选择必要列"]
|
|
AggQuery --> GroupBy["按条件分组"]
|
|
Limit --> Return["返回结果"]
|
|
SelectCols --> Return
|
|
GroupBy --> Return
|
|
Return --> End([查询结束])
|
|
```
|
|
|
|
#### 性能优化策略
|
|
|
|
1. **索引设计**: 在常用查询字段上建立索引
|
|
2. **投影优化**: 只选择需要的字段
|
|
3. **分页处理**: 使用LIMIT和OFFSET进行分页
|
|
4. **批量操作**: 使用批量插入和更新
|
|
|
|
### 数据完整性保证
|
|
|
|
#### 约束策略
|
|
|
|
虽然当前未实现外键约束,但通过以下机制保证数据完整性:
|
|
|
|
1. **业务层验证**: 在路由层进行数据验证
|
|
2. **唯一性约束**: 品牌名称的唯一性保证
|
|
3. **枚举值限制**: 状态字段的取值范围控制
|
|
|
|
#### 级联操作
|
|
|
|
由于缺乏外键约束,级联操作通过业务逻辑实现:
|
|
|
|
```mermaid
|
|
flowchart TD
|
|
DeleteBrand["删除品牌"] --> CheckModels["检查型号关联"]
|
|
CheckModels --> HasModels{"是否有型号关联?"}
|
|
HasModels --> |是| BlockDelete["阻止删除"]
|
|
HasModels --> |否| ProceedDelete["允许删除"]
|
|
BlockDelete --> LogWarn["记录警告日志"]
|
|
ProceedDelete --> CascadeOps["执行级联操作"]
|
|
CascadeOps --> UpdateOta["更新OTA关联"]
|
|
UpdateOta --> Complete["完成删除"]
|
|
```
|
|
|
|
**图表来源**
|
|
- [brands.js:125-144](file://backend/src/routes/brands.js#L125-L144)
|
|
|
|
**章节来源**
|
|
- [brands.js:14-144](file://backend/src/routes/brands.js#L14-L144)
|
|
- [models.js:133-464](file://backend/src/routes/models.js#L133-L464)
|
|
- [ota.js:107-268](file://backend/src/routes/ota.js#L107-L268)
|
|
|
|
## 依赖关系分析
|
|
|
|
### 模块依赖图
|
|
|
|
```mermaid
|
|
graph LR
|
|
subgraph "核心模块"
|
|
APP[app.js]
|
|
DB[database.js]
|
|
MODELS_INDEX[models/index.js]
|
|
end
|
|
subgraph "模型层"
|
|
BRAND[Brand.js]
|
|
MODEL[Model.js]
|
|
OTA[Ota.js]
|
|
end
|
|
subgraph "路由层"
|
|
BRAND_ROUTE[brands.js]
|
|
MODEL_ROUTE[models.js]
|
|
OTA_ROUTE[ota.js]
|
|
end
|
|
subgraph "验证层"
|
|
OTA_VALIDATOR[validators/ota.js]
|
|
end
|
|
APP --> DB
|
|
APP --> MODELS_INDEX
|
|
MODELS_INDEX --> BRAND
|
|
MODELS_INDEX --> MODEL
|
|
MODELS_INDEX --> OTA
|
|
BRAND_ROUTE --> BRAND
|
|
MODEL_ROUTE --> MODEL
|
|
OTA_ROUTE --> OTA
|
|
OTA_ROUTE --> OTA_VALIDATOR
|
|
```
|
|
|
|
**图表来源**
|
|
- [app.js:1-60](file://backend/src/app.js#L1-L60)
|
|
- [index.js:1-8](file://backend/src/models/index.js#L1-L8)
|
|
- [brands.js:1-10](file://backend/src/routes/brands.js#L1-L10)
|
|
- [models.js:1-16](file://backend/src/routes/models.js#L1-L16)
|
|
- [ota.js:1-20](file://backend/src/routes/ota.js#L1-L20)
|
|
|
|
### 外部依赖
|
|
|
|
系统依赖的关键外部库:
|
|
|
|
- **Sequelize**: ORM框架,提供数据库抽象层
|
|
- **Express.js**: Web框架,处理HTTP请求
|
|
- **Multer**: 文件上传中间件
|
|
- **Zod**: 数据验证库
|
|
- **Axios**: HTTP客户端
|
|
|
|
**章节来源**
|
|
- [app.js:1-60](file://backend/src/app.js#L1-L60)
|
|
- [models.js:1-16](file://backend/src/routes/models.js#L1-L16)
|
|
- [ota.js:1-20](file://backend/src/routes/ota.js#L1-L20)
|
|
|
|
## 性能考虑
|
|
|
|
### 查询优化策略
|
|
|
|
#### 索引设计建议
|
|
|
|
1. **主键索引**: 自动为所有表的主键创建索引
|
|
2. **唯一索引**: 为品牌名称创建唯一索引
|
|
3. **复合索引**: 为常用查询组合创建复合索引
|
|
4. **全文索引**: 为搜索功能考虑全文索引
|
|
|
|
#### 分页查询优化
|
|
|
|
```mermaid
|
|
flowchart TD
|
|
QueryStart["查询开始"] --> CountTotal["统计总数"]
|
|
CountTotal --> CheckPage["检查页码范围"]
|
|
CheckPage --> ValidPage{"页码有效?"}
|
|
ValidPage --> |否| Error["返回错误"]
|
|
ValidPage --> |是| CalcOffset["计算偏移量"]
|
|
CalcOffset --> ApplyLimit["应用LIMIT"]
|
|
ApplyLimit --> ExecuteQuery["执行查询"]
|
|
ExecuteQuery --> ReturnResults["返回结果"]
|
|
Error --> End["结束"]
|
|
ReturnResults --> End
|
|
```
|
|
|
|
#### 批量操作优化
|
|
|
|
1. **批量插入**: 使用批量插入减少数据库往返
|
|
2. **事务处理**: 对复杂操作使用事务保证一致性
|
|
3. **连接池**: 合理配置数据库连接池大小
|
|
|
|
## 故障排除指南
|
|
|
|
### 常见问题及解决方案
|
|
|
|
#### 数据库连接问题
|
|
|
|
**症状**: 应用启动时数据库连接失败
|
|
**原因**: 环境变量配置错误或数据库服务不可用
|
|
**解决方案**:
|
|
1. 检查DATABASE_HOST、DATABASE_PORT、DATABASE_NAME等环境变量
|
|
2. 确认MySQL服务正在运行
|
|
3. 验证用户名和密码正确性
|
|
|
|
#### 数据验证错误
|
|
|
|
**症状**: API请求返回验证错误
|
|
**原因**: 请求数据不符合验证规则
|
|
**解决方案**:
|
|
1. 检查请求数据格式
|
|
2. 确认必填字段完整
|
|
3. 验证数据类型和长度限制
|
|
|
|
#### 查询性能问题
|
|
|
|
**症状**: 查询响应时间过长
|
|
**原因**: 缺少适当的索引或查询条件不当
|
|
**解决方案**:
|
|
1. 分析慢查询日志
|
|
2. 添加必要的索引
|
|
3. 优化查询条件
|
|
4. 实施分页策略
|
|
|
|
**章节来源**
|
|
- [brands.js:36-39](file://backend/src/routes/brands.js#L36-L39)
|
|
- [models.js:177-180](file://backend/src/routes/models.js#L177-L180)
|
|
- [ota.js:139-142](file://backend/src/routes/ota.js#L139-L142)
|
|
|
|
## 结论
|
|
|
|
本实体关系设计文档详细阐述了Brand、Model、Ota三个核心实体的设计理念和实现方案。当前系统采用简化的无外键设计,在灵活性和性能之间取得了平衡。建议在未来版本中:
|
|
|
|
1. **实现显式关联**: 添加Sequelize关联定义
|
|
2. **完善约束**: 建立外键约束确保数据完整性
|
|
3. **优化查询**: 实现更高效的关联查询
|
|
4. **增强监控**: 添加数据库性能监控
|
|
|
|
通过这些改进,可以在保持系统灵活性的同时,进一步提升数据一致性和查询性能。 |