使用 pgdoc
启用 pgdoc 后,客户端仍按文档型数据库的方式读写数据,请求由 PostgreSQL 承载。启用步骤与开通报错见 插件概述。
本页按“接入 → 数据读写 → 权限 → 索引”的顺序给出具体做法。客户端代码分小程序端与 Web 端两个标签页,服务端写法单独标注。
接入
初始化只需要环境 ID,不需要 PostgreSQL 连接串:
- 小程序
- Web 端
const db = wx.cloud.database()
import cloudbase from '@cloudbase/js-sdk'
const app = cloudbase.init({ env: 'your-env-id' })
const db = app.database()
服务端(云函数、Node.js)用 @cloudbase/node-sdk 初始化,写法见事务与聚合示例。
SDK 接口参考:小程序 SDK、JS SDK 数据库、Node SDK 数据库。
数据读写
数据结构仍是 JSON 文档,字段类型有 String、Number、Object、Array、Bool、Date、GeoPoint、Null 八种。Date 用 new Date() 表示客户端时间,db.serverDate() 表示服务端时间。
增删改查
- 小程序
- Web 端
const todos = db.collection('todos')
// 新增
await todos.add({ data: { title: '写文档', done: false } })
// 查询
const { data } = await todos
.where({ done: false })
.orderBy('createdAt', 'desc')
.limit(20)
.get()
// 更新
await todos.doc('todo-id').update({ data: { done: true } })
// 删除
await todos.doc('todo-id').remove()
const todos = db.collection('todos')
// 新增
await todos.add({ title: '写文档', done: false })
// 查询
const result = await todos
.where({ done: false })
.orderBy('createdAt', 'desc')
.limit(20)
.get()
// 更新
await todos.doc('todo-id').update({ done: true })
小程序端的新增与更新要包一层 data,Web 端直接传数据对象。Web 端删除文档见 删除数据。
地理位置查询
- 小程序
- Web 端
// 写入地理位置
await db.collection('stores').add({
data: { name: '北京店', location: db.Geo.Point(116.4, 39.9) },
})
// 按距离查询
const _ = db.command
await db
.collection('stores')
.where({
location: _.geoNear({
geometry: db.Geo.Point(116.4, 39.9),
minDistance: 1000,
maxDistance: 5000,
}),
})
.limit(10)
.get()
// 写入地理位置
await db.collection('stores').add({
name: '北京店',
location: new db.Geo.Point(116.4, 39.9),
})
// 按距离查询
const _ = db.command
await db
.collection('stores')
.where({
location: _.geoNear({
geometry: new db.Geo.Point(116.4, 39.9),
minDistance: 1000,
maxDistance: 5000,
}),
})
.limit(10)
.get()
geoNear 只接受 geometry、minDistance、maxDistance 三个参数,限制返回条数要链式调用 limit()。
⚠️ 注意:查询地理位置字段前必须先建地理位置索引,否则查询失败。
事务
事务保证多步操作要么全部成功要么全部失败,单个事务会话最长 30 秒。手动控制提交与回滚用 startTransaction 配合 commit / rollback,服务端还可以用 runTransaction 自动提交:
- 小程序
- Web 端
- 服务端
const transaction = await db.startTransaction()
try {
await transaction.collection('todos').doc('todo-id').update({
data: { completed: true },
})
await transaction.collection('users').doc('user-id').update({
data: { completedTodos: db.command.inc(1) },
})
await transaction.commit()
} catch (err) {
await transaction.rollback()
throw err
}
const transaction = await db.startTransaction()
try {
await transaction.collection('todos').doc('todo-id').update({ completed: true })
await transaction
.collection('users')
.doc('user-id')
.update({ completedTodos: db.command.inc(1) })
await transaction.commit()
} catch (err) {
await transaction.rollback()
throw err
}
const cloudbase = require('@cloudbase/node-sdk')
const app = cloudbase.init({ env: 'your-env-id' })
const db = app.database()
await db.runTransaction(async (transaction) => {
await transaction.collection('todos').doc('todo-id').update({
data: { completed: true },
})
await transaction.collection('users').doc('user-id').update({
data: { completedTodos: db.command.inc(1) },
})
})
服务端也可用 startTransaction 手动控制,写法与上面两个客户端示例一致。
聚合
聚合按阶段流水线处理,适合统计与分组:
const $ = db.command.aggregate
const res = await db
.collection('books')
.aggregate()
.match({ onSale: true })
.group({ _id: '$category', avgSales: $.avg('$sales') })
.end()
💡 提示:聚合的计算开销随数据量放大。先用
match缩小数据集再进入group,或用project只保留需要的字段,能明显降低耗时。
权限管理
pgdoc 只支持基础权限,不支持安全规则。权限在控制台的集合管理页配置,按 _openid 字段判定数据归属:
| 权限类型 | 适用场景 |
|---|---|
| 读取全部数据,修改本人数据 | 公开内容,如文章、商品 |
| 读取和修改本人数据 | 私人数据,如用户资料 |
| 读取全部数据,不可修改数据 | 配置数据,如系统设置 |
| 无权限 | 敏感数据,如财务信息 |
原本依赖安全规则的集合,启用前要改为基础权限,或把校验放到云函数等服务端逻辑里,不要只靠客户端判断。
直接在 PostgreSQL 中读写时,权限按 GRANT 与 RLS 判定,参见 PostgreSQL 数据权限。
索引管理
索引在控制台的集合索引管理页维护,支持单字段、组合、地理位置、唯一四类。按实际过滤字段建索引,例如常按 done 与 createdAt 查询,就建 done 单字段索引或 done + createdAt 组合索引。
- 单集合最多 64 个索引(含
_id),复合索引最多 32 个键,索引越多写入越慢 - 正则表达式查询无法使用索引
- 地理位置查询必须有地理位置索引,参见地理位置查询
HTTP API 与 SDK 兼容说明
pgdoc 复用文档型数据库的请求入口,客户端不需要改域名或请求体。支持的入口如下:
| 类型 | 支持的入口 |
|---|---|
| HTTP API | 文档型数据库 HTTP API,请求域名与路径不变 |
| 小程序端 | 小程序 SDK |
| Web 端 | JS SDK |
| 服务端 | wx-server-sdk 2.x / 4.x、Node SDK v3 /admin、Node SDK v4 gateway /v1 |
⚠️ 注意:部分能力不在支持范围,见使用限制。
使用限制
以下为 pgdoc 的硬性上限,超出会直接报错:
| 项目 | 上限 |
|---|---|
| 单条文档(BSON) | 16 MiB |
| 单次批量写 | 25,000 条 |
| 单集合索引数 | 64 个(含 _id) |
| 复合索引键 | 32 个 |
| 单次查询返回 | 默认 50 MiB,经云 API 返回 10 MiB |
| 单请求游标页数 | 4096 页 |
| 事务会话时长 | 30 秒 |
| 导入单批条数 | 1000 条 |
与文档型数据库相比,以下能力 pgdoc 不支持:
- 跨请求游标:单次请求内读完,不返回可持续读取的游标,大结果集需要一次取完
- 特殊集合:timeseries、clustered、change stream
💡 提示:
pgdoc支持 16 位与 24 位_id;NaN、Infinity 按标准 EJSON 返回;普通字段的$oid查询同时匹配原生 ObjectId 与旧嵌入对象。这些在文档型数据库上受限的写法,迁移后可以直接用。