Files
leaudit-platform-frontend/auth_doc/前端对接文档-PostgREST查询参考.md
T
2025-11-18 11:06:24 +08:00

317 lines
7.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# PostgREST查询参考
## 过滤运算符完整列表
### 比较运算符
| 运算符 | 说明 | PostgREST语法 | JavaScript示例 |
|--------|------|---------------|----------------|
| eq | 等于 | `field=eq.value` | `{ field: 'eq.value' }` |
| neq | 不等于 | `field=neq.value` | `{ field: 'neq.value' }` |
| gt | 大于 | `field=gt.value` | `{ field: 'gt.100' }` |
| gte | 大于等于 | `field=gte.value` | `{ field: 'gte.100' }` |
| lt | 小于 | `field=lt.value` | `{ field: 'lt.100' }` |
| lte | 小于等于 | `field=lte.value` | `{ field: 'lte.100' }` |
### 模式匹配运算符
| 运算符 | 说明 | PostgREST语法 | JavaScript示例 |
|--------|------|---------------|----------------|
| like | 模糊匹配(区分大小写) | `field=like.*pattern*` | `{ field: 'like.*测试*' }` |
| ilike | 模糊匹配(不区分大小写) | `field=ilike.*pattern*` | `{ field: 'ilike.*TEST*' }` |
**模式匹配通配符**:
- `*`: 匹配任意字符(等同于SQL的`%`
- `_`: 匹配单个字符
**示例**:
```javascript
// 查询标题以"合同"开头的文档
{ title: 'like.合同*' }
// 查询标题以"合同"结尾的文档
{ title: 'like.*合同' }
// 查询标题包含"合同"的文档
{ title: 'like.*合同*' }
// 不区分大小写查找
{ title: 'ilike.*contract*' }
```
### 列表运算符
| 运算符 | 说明 | PostgREST语法 | JavaScript示例 |
|--------|------|---------------|----------------|
| in | 在列表中 | `field=in.(value1,value2,...)` | `{ field: 'in.(active,pending)' }` |
| cs | 包含(数组字段) | `field=cs.{value1,value2}` | `{ tags: 'cs.{重要,紧急}' }` |
| cd | 被包含(数组字段) | `field=cd.{value1,value2}` | `{ tags: 'cd.{重要,紧急}' }` |
| ov | 重叠(数组字段) | `field=ov.{value1,value2}` | `{ tags: 'ov.{重要,紧急}' }` |
**示例**:
```javascript
// 查询状态为active或pending的文档
{ status: 'in.(active,pending)' }
// 查询ID在[1, 2, 3]中的文档
{ id: 'in.(1,2,3)' }
// 查询标签包含"重要"和"紧急"的文档(数组字段)
{ tags: 'cs.{重要,紧急}' }
```
### Null检查运算符
| 运算符 | 说明 | PostgREST语法 | JavaScript示例 |
|--------|------|---------------|----------------|
| is | 是null | `field=is.null` | `{ field: 'is.null' }` |
| nt | 不是null | `field=nt.null` (或 `is.not.null`) | `{ field: 'nt.null' }` |
**示例**:
```javascript
// 查询deleted_at为null的文档(未删除)
{ deleted_at: 'is.null' }
// 查询deleted_at不为null的文档(已删除)
{ deleted_at: 'nt.null' }
```
## 排序
### 单字段排序
```javascript
// 按创建时间升序
{ order: 'created_at.asc' }
// 按创建时间降序
{ order: 'created_at.desc' }
```
### 多字段排序
```javascript
// 先按状态升序,再按创建时间降序
{ order: 'status.asc,created_at.desc' }
```
## 分页
### Limit和Offset
```javascript
// 每页10条,第1页
{ limit: 10, offset: 0 }
// 每页10条,第2页
{ limit: 10, offset: 10 }
// 每页20条,第3页
{ limit: 20, offset: 40 }
```
### 获取总数
PostgREST会在响应头中返回`Content-Range`,包含总记录数:
```
Content-Range: 0-9/50
```
表示:返回第0-9条记录,总共50条记录。
**解析示例**:
```javascript
const response = await apiClient.get('/postgrest/documents', {
params: { limit: 10, offset: 0 }
});
const contentRange = response.headers['content-range'];
const total = parseInt(contentRange.split('/')[1]); // 50
```
## 字段选择
### 选择特定字段
```javascript
// 只返回id, title, status字段
{ select: 'id,title,status' }
```
### 嵌套查询(外键关联)
PostgREST支持嵌套查询,但DocAuditAI暂未启用此功能。
## 高级查询
### 逻辑运算符
**注意**: 前端应避免使用`or``and``not`参数,这些参数由后端自动生成(用于数据范围和交叉评查权限)。
### 复杂查询示例
```javascript
// 查询状态为active且创建时间在2025年之后的文档,按创建时间降序,每页10条
const params = {
status: 'eq.active',
created_at: 'gte.2025-01-01',
order: 'created_at.desc',
limit: 10,
offset: 0
};
const response = await apiClient.get('/postgrest/documents', { params });
```
## 完整示例
### 示例1:文档列表查询
```javascript
// 需求:查询标题包含"合同"、状态为active的文档,
// 按创建时间降序排列,每页20条,第2页
async function getDocumentList() {
const response = await apiClient.get('/postgrest/documents', {
params: {
title: 'ilike.*合同*',
status: 'eq.active',
order: 'created_at.desc',
limit: 20,
offset: 20 // 第2页
}
});
return {
data: response.data,
total: parseInt(response.headers['content-range'].split('/')[1])
};
}
```
### 示例2:高级搜索
```javascript
// 需求:搜索2025年创建的、状态为active或pending的文档
async function advancedSearch() {
const response = await apiClient.get('/postgrest/documents', {
params: {
status: 'in.(active,pending)',
created_at: 'gte.2025-01-01',
created_at: 'lt.2026-01-01', // 注意:PostgREST会组合多个同名参数
order: 'created_at.desc'
}
});
return response.data;
}
```
### 示例3:分页封装
```javascript
// 通用分页函数
async function fetchPaginated(table, page, pageSize, filters = {}) {
const params = {
limit: pageSize,
offset: (page - 1) * pageSize,
...filters
};
const response = await apiClient.get(`/postgrest/${table}`, { params });
const contentRange = response.headers['content-range'];
const total = contentRange ? parseInt(contentRange.split('/')[1]) : 0;
return {
data: response.data,
total: total,
page: page,
pageSize: pageSize,
totalPages: Math.ceil(total / pageSize)
};
}
// 使用示例
const result = await fetchPaginated('documents', 1, 10, {
status: 'eq.active',
order: 'created_at.desc'
});
console.log(`${result.total}条记录,第${result.page}/${result.totalPages}`);
```
## 性能优化建议
### 1. 始终使用分页
```javascript
// ✅ 好的做法
{ limit: 10, offset: 0 }
// ❌ 不好的做法(返回所有数据)
{}
```
### 2. 只查询需要的字段
```javascript
// ✅ 好的做法(只查询id和title)
{ select: 'id,title' }
// ❌ 不好的做法(查询所有字段)
{}
```
### 3. 使用索引字段进行过滤
优先使用已建立索引的字段(如id, user_id, ou_id, status)进行过滤,提升查询性能。
### 4. 避免过度模糊查询
```javascript
// ✅ 好的做法(明确的过滤条件)
{ title: 'like.合同*' }
// ❌ 不好的做法(前后通配符,性能差)
{ title: 'like.*合同*' }
```
## 常见错误
### 错误1:运算符拼写错误
```javascript
// ❌ 错误
{ status: 'equal.active' } // 应该是 eq
// ✅ 正确
{ status: 'eq.active' }
```
### 错误2:日期格式错误
```javascript
// ❌ 错误
{ created_at: 'gte.2025/01/01' } // 格式错误
// ✅ 正确
{ created_at: 'gte.2025-01-01' } // ISO 8601格式
```
### 错误3in运算符语法错误
```javascript
// ❌ 错误
{ status: 'in.active,pending' } // 缺少括号
// ✅ 正确
{ status: 'in.(active,pending)' }
```
## 参考资料
- [PostgREST官方文档](https://postgrest.org/en/stable/)
- [PostgREST API查询语法](https://postgrest.org/en/stable/api.html#horizontal-filtering-rows)