232 lines
5.5 KiB
Markdown
232 lines
5.5 KiB
Markdown
# UTS Supabase Count API 使用示例
|
||
|
||
## 新增的 Count API
|
||
|
||
基于对 Supabase 官方 SDK count 操作符的分析,我们在 `aksupa.uts` 中添加了更符合官方习惯的 count API。
|
||
|
||
## 新增的方法
|
||
|
||
### 1. count() 方法
|
||
```typescript
|
||
count(option: CountOption = 'exact'): AkSupaQueryBuilder
|
||
```
|
||
- **参数**:`'exact' | 'planned' | 'estimated'`
|
||
- **默认**:`'exact'`
|
||
- **效果**:自动启用 `head: true` 模式,只返回 count 不返回数据
|
||
|
||
### 2. 便捷方法
|
||
```typescript
|
||
countExact(): AkSupaQueryBuilder // 等同于 count('exact')
|
||
countEstimated(): AkSupaQueryBuilder // 等同于 count('estimated')
|
||
countPlanned(): AkSupaQueryBuilder // 等同于 count('planned')
|
||
```
|
||
|
||
### 3. head() 方法
|
||
```typescript
|
||
head(enable: boolean = true): AkSupaQueryBuilder
|
||
```
|
||
- **效果**:启用 head 模式,只返回元数据,不返回实际数据
|
||
|
||
## 使用示例对比
|
||
|
||
### 旧用法(仍然支持)
|
||
```typescript
|
||
// 只获取 count
|
||
const result = await supa
|
||
.from('assignments')
|
||
.select('', { count: 'exact', head: true })
|
||
.eq('teacher_id', userId)
|
||
.execute();
|
||
const total = result.total;
|
||
|
||
// 获取数据和 count
|
||
const result = await supa
|
||
.from('assignments')
|
||
.select('*', { count: 'exact' })
|
||
.eq('teacher_id', userId)
|
||
.execute();
|
||
```
|
||
|
||
### 新用法(推荐)
|
||
```typescript
|
||
// 只获取 count - 更简洁
|
||
const result = await supa
|
||
.from('assignments')
|
||
.eq('teacher_id', userId)
|
||
.countExact()
|
||
.execute();
|
||
const total = result.count; // 注意:使用 count 属性
|
||
|
||
// 获取数据和 count
|
||
const result = await supa
|
||
.from('assignments')
|
||
.eq('teacher_id', userId)
|
||
.select('*')
|
||
.count('exact')
|
||
.head(false) // 关闭 head 模式
|
||
.execute();
|
||
```
|
||
|
||
## 实际应用:教师仪表板更新
|
||
|
||
### 更新前
|
||
```typescript
|
||
const assignmentStatsResponse = await supa
|
||
.from('ak_assignments')
|
||
.select('', { count: 'exact', head: true })
|
||
.eq('teacher_id', currentUser)
|
||
.execute()
|
||
|
||
const totalAssignments = assignmentStatsResponse.total
|
||
```
|
||
|
||
### 更新后
|
||
```typescript
|
||
const assignmentStatsResponse = await supa
|
||
.from('ak_assignments')
|
||
.eq('teacher_id', currentUser)
|
||
.countExact()
|
||
.execute()
|
||
|
||
const totalAssignments = assignmentStatsResponse.count
|
||
```
|
||
|
||
## 性能优势
|
||
|
||
### Head 模式的优势
|
||
1. **减少数据传输**:只返回 count 和元数据,不返回实际行数据
|
||
2. **降低内存使用**:客户端无需处理大量数据
|
||
3. **提升响应速度**:网络传输量大幅减少
|
||
|
||
### 自动优化
|
||
- `countExact()` 等方法自动启用 `head: true`
|
||
- 自动设置正确的 Prefer header
|
||
- 自动处理响应解析
|
||
|
||
## API 设计对比
|
||
|
||
### Supabase JavaScript SDK
|
||
```javascript
|
||
const { count } = await supabase
|
||
.from('table')
|
||
.select('*', { count: 'exact', head: true })
|
||
```
|
||
|
||
### Supabase Swift SDK
|
||
```swift
|
||
let count = try await supabase
|
||
.from("table")
|
||
.select("*", count: .exact)
|
||
.execute(head: true)
|
||
.count
|
||
```
|
||
|
||
### 我们的 UTS API
|
||
```typescript
|
||
const { count } = await supa
|
||
.from('table')
|
||
.countExact()
|
||
.execute()
|
||
```
|
||
|
||
## 兼容性
|
||
|
||
### 向后兼容
|
||
- 旧的 `getcount` 参数仍然支持
|
||
- 旧的 `select('', { count: 'exact', head: true })` 语法仍然工作
|
||
- 响应格式保持一致
|
||
|
||
### 类型安全
|
||
```typescript
|
||
export type CountOption = 'exact' | 'planned' | 'estimated';
|
||
|
||
export type AkSupaSelectOptions = {
|
||
count?: CountOption; // 新增
|
||
head?: boolean; // 新增
|
||
getcount?: string; // 保持向后兼容
|
||
// ...其他选项
|
||
};
|
||
```
|
||
|
||
## 响应格式
|
||
|
||
### Head 模式响应
|
||
```typescript
|
||
{
|
||
data: null, // head 模式不返回数据
|
||
count: 42, // 统计结果
|
||
total: 42, // 同 count
|
||
page: 1,
|
||
limit: 0,
|
||
hasmore: false, // head 模式不需要分页
|
||
origin: {...}, // 原始响应
|
||
status: 200,
|
||
headers: {...},
|
||
error: null
|
||
}
|
||
```
|
||
|
||
### 普通模式响应
|
||
```typescript
|
||
{
|
||
data: [...], // 实际数据
|
||
count: 42, // 总数统计
|
||
total: 42, // 同 count
|
||
page: 1,
|
||
limit: 10,
|
||
hasmore: true,
|
||
origin: {...},
|
||
status: 200,
|
||
headers: {...},
|
||
error: null
|
||
}
|
||
```
|
||
|
||
## 最佳实践建议
|
||
|
||
### 1. 纯统计查询
|
||
```typescript
|
||
// ✅ 推荐:使用 countExact()
|
||
const { count } = await supa.from('table').eq('status', 'active').countExact().execute();
|
||
|
||
// ❌ 不推荐:获取所有数据再计算长度
|
||
const { data } = await supa.from('table').eq('status', 'active').select('*').execute();
|
||
const count = data.length;
|
||
```
|
||
|
||
### 2. 数据+统计
|
||
```typescript
|
||
// ✅ 推荐:一次请求获取数据和总数
|
||
const result = await supa
|
||
.from('table')
|
||
.select('*')
|
||
.count('exact')
|
||
.head(false)
|
||
.limit(10)
|
||
.execute();
|
||
|
||
// ❌ 不推荐:两次请求
|
||
const countResult = await supa.from('table').countExact().execute();
|
||
const dataResult = await supa.from('table').select('*').limit(10).execute();
|
||
```
|
||
|
||
### 3. 性能考虑
|
||
```typescript
|
||
// ✅ 大表统计使用 estimated
|
||
const { count } = await supa.from('huge_table').countEstimated().execute();
|
||
|
||
// ✅ 精确统计使用 exact
|
||
const { count } = await supa.from('small_table').countExact().execute();
|
||
```
|
||
|
||
## 总结
|
||
|
||
新的 count API 提供了:
|
||
1. **更简洁的语法**:直接调用 `countExact()` 而不是复杂的参数
|
||
2. **更好的性能**:自动启用 head 模式优化
|
||
3. **更好的类型安全**:CountOption 枚举
|
||
4. **完全向后兼容**:不破坏现有代码
|
||
5. **符合官方习惯**:API 设计对齐 Supabase 官方 SDK
|
||
|
||
推荐在新代码中使用新的 count API,现有代码可以逐步迁移。
|