跳转到内容

集合与字段

集合(Collection)是 PocketBase 中数据组织的基本单位,类似于传统数据库中的表。理解集合的设计原理和字段配置是构建高效应用的基础。

Base 集合用于存储普通数据,如文章、评论、配置等。

特点:

  • 标准 CRUD 操作
  • 支持所有字段类型
  • 通过规则控制访问权限

适用场景:

  • 博客文章
  • 商品信息
  • 系统配置
  • 日志记录

Auth 集合专门用于用户认证,在 Base 集合的基础上增加了认证相关功能。

内置字段:

字段名类型说明
idtext主键
collectionIdtext集合 ID
collectionNametext集合名称
usernametext用户名(可选)
emailemail邮箱(可选)
emailVisibilitybool邮箱是否对其他用户可见
verifiedbool邮箱是否已验证
tokenKeytext用于重置密码的 token
passwordpassword加密存储的密码
passwordHashtext密码哈希值
passwordConfirmpassword密码确认(创建时)
createddate创建时间
updateddate更新时间

扩展字段示例:

// Auth 集合可以添加自定义字段
{
"name": "users",
"type": "auth",
"fields": [
// 内置字段...
{ "name": "role", "type": "select", "options": ["user", "admin", "moderator"] },
{ "name": "avatar", "type": "file" },
{ "name": "bio", "type": "text" },
{ "name": "githubId", "type": "text" },
{ "name": "settings", "type": "json" }
]
}

单行文本字段,适合短文本内容。

{
"name": "title",
"type": "text",
"required": true,
"options": {
"min": 1,
"max": 200
}
}

使用场景: 标题、名称、用户名

富文本编辑器字段,通常存储 HTML。

{
"name": "content",
"type": "editor",
"required": true
}

使用场景: 文章内容、页面内容、描述

数字字段,支持整数和小数。

{
"name": "price",
"type": "number",
"required": true,
"options": {
"min": 0,
"max": 1000000
}
}

使用场景: 价格、数量、评分、排序权重

日期时间字段,存储 ISO 8601 格式。

{
"name": "publishedAt",
"type": "date"
}

使用场景: 发布时间、过期时间、生日

布尔值字段,true/false。

{
"name": "featured",
"type": "bool",
"options": {
"default": false
}
}

使用场景: 是否推荐、是否启用、开关状态

邮箱字段,自动验证格式。

{
"name": "contactEmail",
"type": "email"
}

URL 字段,自动验证格式。

{
"name": "website",
"type": "url"
}

单选下拉框。

{
"name": "status",
"type": "select",
"required": true,
"options": {
"values": ["draft", "published", "archived"],
"default": "draft"
}
}

支持选择多个值。

{
"name": "tags",
"type": "select",
"options": {
"values": ["javascript", "python", "go", "rust"],
"maxSelect": 3
}
}

关联其他集合的记录。

{
"name": "author",
"type": "relation",
"required": true,
"options": {
"collectionId": "pbc_users_collection_id",
"cascadeDelete": false,
"minSelect": 1,
"maxSelect": 1
}
}

关联配置:

选项说明
collectionId关联的集合 ID
cascadeDelete删除记录时是否同时删除关联记录
minSelect最少选择数量
maxSelect最多选择数量(1 表示单选)

一对多关系:

// Post 集合
{
"name": "category",
"type": "relation",
"options": {
"collectionId": "categories_id",
"maxSelect": 1 // 一对多
}
}
// Category 集合(反向关联)
{
"name": "posts",
"type": "relation",
"options": {
"collectionId": "posts_id",
"maxSelect": null // 一对多
}
}

多对多关系:

// Article 集合
{
"name": "tags",
"type": "relation",
"options": {
"collectionId": "tags_id",
"maxSelect": null
}
}

文件上传字段。

{
"name": "avatar",
"type": "file",
"required": false,
"options": {
"maxSelect": 1,
"maxSize": 5242880, // 5MB
"mimeTypes": ["image/jpeg", "image/png", "image/webp"],
"protected": false // 公开访问
}
}

多文件上传:

{
"name": "gallery",
"type": "file",
"options": {
"maxSelect": 10,
"maxSize": 10485760, // 10MB
"mimeTypes": ["image/*", "video/mp4"],
"thumbs": ["200x200", "800x600"]
}
}

存储 JSON 数据,适合灵活的结构。

{
"name": "metadata",
"type": "json",
"options": {}
}

使用场景:

  • 用户偏好设置
  • 动态配置
  • 扩展属性
  • 第三方数据

索引能显著提升查询性能,但会增加写入开销。以下场景建议创建索引:

  1. 高频过滤字段
  2. 排序字段
  3. 关联查询的外键
  4. 唯一性约束字段
{
"name": "status_idx",
"type": "index",
"options": {
"fields": ["status"]
}
}
{
"name": "user_resource_idx",
"type": "index",
"options": {
"fields": ["userId", "resourceId"],
"unique": true
}
}

确保字段值唯一:

{
"name": "slug_unique",
"type": "index",
"options": {
"fields": ["slug"],
"unique": true
}
}
// 文章列表查询优化
// 查询: filter=status='published' && sort=-publishedAt
{
"name": "posts_list_idx",
"type": "index",
"options": {
"fields": ["status", "publishedAt"]
}
}
// 用户登录优化
// 查询: filter=username='xxx' || email='xxx'
{
"name": "user_login_idx",
"type": "index",
"options": {
"fields": ["username"]
}
}
{
"name": "user_email_idx",
"type": "index",
"options": {
"fields": ["email"],
"unique": true
}
}
// 关联查询优化
// 查询: filter=authorId='xxx' && sort=-created
{
"name": "posts_author_idx",
"type": "index",
"options": {
"fields": ["authorId", "created"]
}
}

规则是布尔表达式,用于控制数据访问权限。

变量说明
@request.auth.id当前登录用户 ID
@request.auth.email当前登录用户邮箱
@request.auth.role当前登录用户角色(自定义字段)
@request.method请求方法(GET/POST/PATCH/DELETE)
@request.query.key查询参数值
@request.data.field请求数据字段值
@request.id请求的记录 ID(update/delete 时)
@collection.name当前集合名称
@collection.id当前集合 ID
@now当前时间戳
// 完全公开
{
"create": "",
"view": "",
"update": "",
"delete": "",
"list": ""
}
// 完全私有(仅管理员)
{
"create": "id = @request.auth.id && @request.auth.role='admin'",
"view": "id = @request.auth.id && @request.auth.role='admin'",
"update": "id = @request.auth.id && @request.auth.role='admin'",
"delete": "id = @request.auth.id && @request.auth.role='admin'",
"list": "id = @request.auth.id && @request.auth.role='admin'"
}
// 用户只能操作自己的数据
{
"create": "", // 允许创建
"view": "owner = @request.auth.id || id = @request.auth.id",
"update": "owner = @request.auth.id || id = @request.auth.id",
"delete": "owner = @request.auth.id || id = @request.auth.id",
"list": "owner = @request.auth.id || id = @request.auth.id"
}
// 博客文章规则
{
"create": "@request.auth.id != ''", // 需要登录
"view": "", // 公开可查看
"update": "author = @request.auth.id || @request.auth.role='admin'",
"delete": "author = @request.auth.id || @request.auth.role='admin'",
"list": "" // 公开可列表
}
  1. 从最小权限开始:默认拒绝,明确允许
  2. 使用角色控制:通过 auth 集合的 role 字段
  3. 测试规则:在 Admin UI 中用不同身份测试
  4. 规则复用:相似的规则保持一致
// posts 集合
{
"name": "posts",
"type": "base",
"fields": [
{ "name": "title", "type": "text", "required": true },
{ "name": "slug", "type": "text", "required": true, "unique": true },
{ "name": "content", "type": "editor", "required": true },
{ "name": "excerpt", "type": "text" },
{ "name": "cover", "type": "file" },
{ "name": "status", "type": "select", "options": {
"values": ["draft", "published", "archived"],
"default": "draft"
}},
{ "name": "category", "type": "relation", "options": {
"collectionId": "categories_id",
"maxSelect": 1
}},
{ "name": "tags", "type": "relation", "options": {
"collectionId": "tags_id"
}},
{ "name": "author", "type": "relation", "options": {
"collectionId": "users_id",
"maxSelect": 1
}},
{ "name": "featured", "type": "bool", "options": {
"default": false
}},
{ "name": "views", "type": "number", "options": {
"default": 0
}},
{ "name": "publishedAt", "type": "date" }
],
"indexes": [
{ "name": "slug_idx", "type": "index", "options": {
"fields": ["slug"], "unique": true
}},
{ "name": "status_published_idx", "type": "index", "options": {
"fields": ["status", "publishedAt"]
}}
],
"rules": {
"create": "@request.auth.id != ''",
"view": "status = 'published' || author = @request.auth.id || @request.auth.role = 'admin'",
"update": "author = @request.auth.id || @request.auth.role = 'admin'",
"delete": "author = @request.auth.id || @request.auth.role = 'admin'",
"list": "status = 'published' || author = @request.auth.id || @request.auth.role = 'admin'"
}
}
// products 集合
{
"name": "products",
"type": "base",
"fields": [
{ "name": "name", "type": "text", "required": true },
{ "name": "slug", "type": "text", "required": true },
{ "name": "description", "type": "editor" },
{ "name": "images", "type": "file", "options": {
"maxSelect": 10
}},
{ "name": "price", "type": "number", "required": true },
{ "name": "comparePrice", "type": "number" },
{ "name": "sku", "type": "text", "unique": true },
{ "name": "stock", "type": "number", "options": {
"default": 0
}},
{ "name": "category", "type": "relation" },
{ "name": "variants", "type": "json" },
{ "name": "active", "type": "bool", "options": {
"default": true
}}
]
}
// orders 集合
{
"name": "orders",
"type": "base",
"fields": [
{ "name": "orderNumber", "type": "text", "required": true, "unique": true },
{ "name": "customer", "type": "relation", "options": {
"collectionId": "users_id",
"maxSelect": 1
}},
{ "name": "items", "type": "json" },
{ "name": "total", "type": "number", "required": true },
{ "name": "status", "type": "select", "options": {
"values": ["pending", "paid", "shipped", "delivered", "cancelled"],
"default": "pending"
}},
{ "name": "shippingAddress", "type": "json" },
{ "name": "paidAt", "type": "date" }
],
"rules": {
"create": "@request.auth.id != ''",
"view": "customer = @request.auth.id || @request.auth.role = 'admin'",
"update": "@request.auth.role = 'admin'",
"delete": "@request.auth.role = 'admin'",
"list": "customer = @request.auth.id || @request.auth.role = 'admin'"
}
}
// comments 集合
{
"name": "comments",
"type": "base",
"fields": [
{ "name": "content", "type": "text", "required": true },
{ "name": "post", "type": "relation", "options": {
"collectionId": "posts_id",
"maxSelect": 1
}},
{ "name": "author", "type": "relation", "options": {
"collectionId": "users_id",
"maxSelect": 1
}},
{ "name": "parent", "type": "relation", "options": {
"collectionId": "comments_id",
"maxSelect": 1
}},
{ "name": "status", "type": "select", "options": {
"values": ["pending", "approved", "rejected"],
"default": "pending"
}}
],
"rules": {
"create": "@request.auth.id != ''",
"view": "status = 'approved' || author = @request.auth.id",
"update": "@request.auth.role = 'admin'",
"delete": "author = @request.auth.id || @request.auth.role = 'admin'",
"list": "status = 'approved' || author = @request.auth.id"
}
}

添加 deletedAt 字段:

{
"name": "deletedAt",
"type": "date"
}

查询时过滤已删除记录:

filter = deletedAt = null;

添加 tenantId 字段:

{
"name": "tenantId",
"type": "text",
"required": true
}

规则中限制:

{
"view": "tenantId = @request.auth.tenantId",
"list": "tenantId = @request.auth.tenantId"
}

使用多选 select 或 relation:

// 简单标签
{
"name": "tags",
"type": "select",
"options": {
"values": ["tag1", "tag2", "tag3"],
"maxSelect": null
}
}
// 复杂关联
{
"name": "tags",
"type": "relation",
"options": {
"collectionId": "tags_id"
}
}
  • relation:需要关联查询、需要级联删除、数据需要独立管理
  • json:简单的嵌入式数据、不需要关联查询、数据结构灵活