Initial commit of akmon project

This commit is contained in:
2026-01-20 08:04:15 +08:00
commit 77a2bab985
1309 changed files with 343305 additions and 0 deletions

View File

@@ -0,0 +1,157 @@
# Supabase Count 查询使用指南
## 基本语法
在 Supabase 中,有几种方式可以获取记录数量:
### 1. 使用 count 选项(推荐)
```typescript
// 基本用法
const response = await supa
.from('table_name')
.select('*', { count: 'exact' })
.execute()
// 结果在 response.count 中
const totalCount = response.count
```
### 2. count 选项的类型
```typescript
// exact: 精确计数(较慢,但准确)
.select('*', { count: 'exact' })
// estimated: 估算计数(较快,但可能不准确)
.select('*', { count: 'estimated' })
// planned: 计划计数(最快,但最不准确)
.select('*', { count: 'planned' })
```
## 实际应用示例
### 修改前(低效方式)
```typescript
// ❌ 不推荐:获取所有数据然后计算长度
const response = await supa
.from('ak_assignments')
.select('id, status')
.eq('teacher_id', userId)
.execute()
const totalCount = response.data?.length || 0
const completedCount = response.data?.filter(a => a.status === 'completed').length || 0
```
**问题**
- 需要传输所有数据
- 浪费网络带宽
- 客户端处理负担重
- 性能差
### 修改后(高效方式)
```typescript
// ✅ 推荐:直接在数据库层面计数
const totalResponse = await supa
.from('ak_assignments')
.select('*', { count: 'exact' })
.eq('teacher_id', userId)
.execute()
const completedResponse = await supa
.from('ak_assignments')
.select('*', { count: 'exact' })
.eq('teacher_id', userId)
.eq('status', 'completed')
.execute()
const totalCount = totalResponse.count || 0
const completedCount = completedResponse.count || 0
```
**优势**
- 只传输计数结果
- 数据库层面计算,效率高
- 网络传输量小
- 客户端处理简单
## 教师仪表板中的应用
### 完整实现
```typescript
// 总作业数
const assignmentStatsResponse = await supa
.from('ak_assignments')
.select('*', { count: 'exact' })
.eq('teacher_id', currentUser)
.execute()
// 已完成作业数
const completedStatsResponse = await supa
.from('ak_assignments')
.select('*', { count: 'exact' })
.eq('teacher_id', currentUser)
.eq('status', 'completed')
.execute()
// 待评阅作业数
const pendingStatsResponse = await supa
.from('ak_assignments')
.select('*', { count: 'exact' })
.eq('teacher_id', currentUser)
.eq('status', 'submitted')
.execute()
// 学生总数
const studentStatsResponse = await supa
.from('ak_users')
.select('*', { count: 'exact' })
.eq('role', 'student')
.execute()
// 处理结果
stats.value = {
total_assignments: assignmentStatsResponse.count || 0,
completed_assignments: completedStatsResponse.count || 0,
pending_review: pendingStatsResponse.count || 0,
total_students: studentStatsResponse.count || 0
}
```
## 性能对比
### 数据量: 1000条记录
| 方式 | 网络传输 | 处理时间 | 内存使用 |
|------|----------|----------|----------|
| 获取全部数据 | ~100KB | ~200ms | 高 |
| 使用 count | ~1KB | ~50ms | 低 |
### 数据量: 10000条记录
| 方式 | 网络传输 | 处理时间 | 内存使用 |
|------|----------|----------|----------|
| 获取全部数据 | ~1MB | ~2s | 很高 |
| 使用 count | ~1KB | ~100ms | 低 |
## 最佳实践
1. **统计查询使用 count**:当只需要数量时,总是使用 count
2. **选择合适的 count 类型**:一般情况用 'exact'
3. **多条件分别查询**:不同条件的计数分别查询,避免复杂的客户端过滤
4. **错误处理**:始终检查 response.count 是否为 null
5. **并行查询**:多个独立的 count 查询可以并行执行
```typescript
// 并行执行多个 count 查询
const [totalResp, completedResp, pendingResp, studentResp] = await Promise.all([
supa.from('ak_assignments').select('*', { count: 'exact' }).eq('teacher_id', userId).execute(),
supa.from('ak_assignments').select('*', { count: 'exact' }).eq('teacher_id', userId).eq('status', 'completed').execute(),
supa.from('ak_assignments').select('*', { count: 'exact' }).eq('teacher_id', userId).eq('status', 'submitted').execute(),
supa.from('ak_users').select('*', { count: 'exact' }).eq('role', 'student').execute()
])
```
这样既提高了性能,又简化了代码逻辑!