168 lines
5.1 KiB
Markdown
168 lines
5.1 KiB
Markdown
# Supabase 数据库适配说明
|
||
|
||
## 概述
|
||
|
||
推送消息接收服务的数据库结构已适配现有的 `ak_users` 和 `ak_devices` 表结构,以避免重复创建表和数据冲突。所有推送消息相关的表都使用 `ps_` 前缀命名。
|
||
|
||
## 主要变更
|
||
|
||
### 1. 移除独立表
|
||
- ❌ 移除独立的 `devices` 表
|
||
- ❌ 移除独立的 `users` 表
|
||
- ✅ 使用现有的 `public.ak_devices` 表
|
||
- ✅ 使用现有的 `public.ak_users` 表
|
||
|
||
### 2. 表命名规范
|
||
- ✅ `ps_push_messages` - 推送消息主表
|
||
- ✅ `ps_push_types` - 推送类型配置表
|
||
- ✅ `ps_message_processing_logs` - 消息处理日志表
|
||
- ✅ `ps_system_stats` - 系统统计表
|
||
|
||
### 3. 修改关联字段
|
||
- `ps_push_messages.user_id`: VARCHAR(255) → UUID,关联到 `public.ak_users(id)`
|
||
- `ps_push_messages.device_id`: VARCHAR(255) → UUID,关联到 `public.ak_devices(id)`
|
||
|
||
#### `ps_push_messages` 表结构
|
||
```sql
|
||
CREATE TABLE ps_push_messages (
|
||
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||
message_id VARCHAR(255),
|
||
push_type VARCHAR(50) NOT NULL,
|
||
user_id UUID REFERENCES public.ak_users(id) ON DELETE SET NULL,
|
||
device_id UUID REFERENCES public.ak_devices(id) ON DELETE SET NULL,
|
||
raw_data JSONB NOT NULL,
|
||
parsed_data JSONB,
|
||
received_at TIMESTAMPTZ DEFAULT NOW(),
|
||
processing_status VARCHAR(20) DEFAULT 'pending',
|
||
-- 其他字段...
|
||
);
|
||
```
|
||
|
||
### 4. 适配表结构
|
||
|
||
#### `public.ak_users` 表结构
|
||
```sql
|
||
CREATE TABLE public.ak_users (
|
||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||
username VARCHAR(64) UNIQUE NOT NULL,
|
||
email VARCHAR(128) UNIQUE NOT NULL,
|
||
password_hash VARCHAR(256) NOT NULL,
|
||
gender VARCHAR(16) DEFAULT 'other',
|
||
birthday DATE,
|
||
height_cm INT,
|
||
weight_kg INT,
|
||
bio TEXT,
|
||
phone VARCHAR(32),
|
||
avatar_url TEXT,
|
||
region_id UUID REFERENCES public.ak_regions(id),
|
||
school_id UUID REFERENCES public.ak_schools(id),
|
||
grade_id UUID REFERENCES public.ak_grades(id),
|
||
class_id UUID REFERENCES public.ak_classes(id),
|
||
role VARCHAR(32) DEFAULT 'student',
|
||
created_at TIMESTAMPTZ DEFAULT now(),
|
||
updated_at TIMESTAMPTZ DEFAULT now(),
|
||
auth_id UUID REFERENCES auth.users(id) ON DELETE CASCADE,
|
||
preferred_language UUID REFERENCES public.ak_languages(id)
|
||
);
|
||
```
|
||
|
||
#### `public.ak_devices` 表结构
|
||
```sql
|
||
CREATE TABLE public.ak_devices (
|
||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||
user_id UUID REFERENCES public.ak_users(id) ON DELETE CASCADE,
|
||
device_type VARCHAR(32) NOT NULL,
|
||
device_name VARCHAR(64),
|
||
device_mac VARCHAR(64),
|
||
bind_time TIMESTAMPTZ DEFAULT now(),
|
||
status VARCHAR(16) DEFAULT 'active',
|
||
extra JSONB
|
||
);
|
||
```
|
||
|
||
### 5. 数据库操作调整
|
||
|
||
#### 设备信息处理
|
||
```javascript
|
||
// 旧方式:自动创建/更新设备
|
||
await this.upsertDevice(deviceData);
|
||
|
||
// 新方式:检查并更新现有设备状态
|
||
await this.upsertDevice({
|
||
device_id: deviceData.device_id, // 必须是现有设备的 UUID
|
||
metadata: deviceData.metadata
|
||
});
|
||
```
|
||
|
||
#### 用户信息处理
|
||
```javascript
|
||
// 旧方式:自动创建/更新用户
|
||
await this.upsertUser(userData);
|
||
|
||
// 新方式:检查现有用户(不自动创建)
|
||
await this.upsertUser({
|
||
user_id: userData.user_id // 必须是现有用户的 UUID
|
||
});
|
||
```
|
||
|
||
## API 调用变更
|
||
|
||
### 推送消息接口
|
||
```javascript
|
||
// 发送推送消息时,user_id 和 device_id 必须使用 UUID 格式
|
||
const response = await fetch('/api/push/message', {
|
||
method: 'POST',
|
||
headers: {
|
||
'Content-Type': 'application/json',
|
||
'X-API-Key': 'your-api-key'
|
||
},
|
||
body: JSON.stringify({
|
||
type: 'HEALTH',
|
||
data: {
|
||
user_id: '123e4567-e89b-12d3-a456-426614174000', // UUID 格式
|
||
device_id: '987fcdeb-51a2-43d7-8f9e-123456789abc', // UUID 格式
|
||
H: 72, // 心率
|
||
O: 98, // 血氧
|
||
T: 36.5 // 体温
|
||
}
|
||
})
|
||
});
|
||
```
|
||
|
||
### 错误处理
|
||
如果推送消息中包含不存在的 user_id 或 device_id:
|
||
- 消息仍会被存储到 `push_messages` 表
|
||
- 会在日志中记录警告信息
|
||
- 不会自动创建用户或设备记录
|
||
|
||
## 部署注意事项
|
||
|
||
### 1. 数据库初始化
|
||
确保在执行 `database/supabase-init.sql` 之前,现有的 `ak_users` 和 `ak_devices` 表已经存在。
|
||
|
||
### 2. 外键约束
|
||
推送消息表与现有表建立了外键关联:
|
||
- `ps_push_messages.user_id` → `public.ak_users(id)`
|
||
- `ps_push_messages.device_id` → `public.ak_devices(id)`
|
||
|
||
### 3. 权限设置
|
||
确保 Supabase Service Role 对现有表有适当的访问权限。
|
||
|
||
## 数据完整性
|
||
|
||
### 推送消息存储
|
||
- ✅ 所有推送消息都会完整存储
|
||
- ✅ 支持 user_id 或 device_id 为 NULL 的情况
|
||
- ✅ 通过外键约束保证数据一致性
|
||
|
||
### 统计和查询
|
||
- ✅ 可以通过关联查询获取用户和设备的详细信息
|
||
- ✅ 统计功能完全兼容现有表结构
|
||
|
||
## 使用建议
|
||
|
||
1. **用户和设备管理**:通过专门的用户管理和设备管理接口创建和维护用户、设备信息
|
||
2. **推送消息**:只负责接收和存储推送消息,不处理用户/设备的创建
|
||
3. **数据关联**:通过外键关联获取完整的用户和设备信息
|
||
4. **监控告警**:监控日志中关于不存在用户/设备的警告信息
|