158 lines
4.3 KiB
Markdown
158 lines
4.3 KiB
Markdown
# 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()
|
||
])
|
||
```
|
||
|
||
这样既提高了性能,又简化了代码逻辑!
|