RaisFastRaisFast
Content Types

关联关系

6 种关联类型,自动创建中间表,查询时自动填充。

关联关系将内容类型连接在一起。通过 field_type = "relation"relation 配置来定义。

关联类型

类型描述外键位置数据格式
one_to_one单条关联记录源表字符串(目标 ID)
one_to_many目标表中的多条记录目标表ID 数组
many_to_one属于源表字符串(目标 ID)
many_to_many通过中间表中间表ID 数组
one_way单向引用源表字符串(目标 ID)
many_way单向多对多中间表ID 数组

Many To One(多对一)

最常见的关联 — "属于"。外键在源表中。

# 每门课程属于一个讲师
[[fields]]
name = "instructor"
field_type = "relation"
relation = { relation_type = "many_to_one", target = "instructors" }

系统会在 courses 表中添加 instructor_id 列。

# 创建课程并关联讲师
curl -X POST http://localhost:9898/api/v1/cms/courses \
  -d '{"title":"Rust 入门","instructor":"<instructor_id>"}'

One To Many(一对多)

"many_to_one 的反向"。外键在目标表中。

# 讲师有很多课程(外键在 courses 表中)
[[fields]]
name = "courses"
field_type = "relation"
relation = { relation_type = "one_to_many", target = "courses" }

不会添加新列 — 它读取目标侧已有的外键。用于反向查询。

Many To Many(多对多)

通过自动创建的中间表关联。

# 课程有多个标签
[[fields]]
name = "tags"
field_type = "relation"
relation = { relation_type = "many_to_many", target = "tags", through = "courses_tags" }

系统自动创建 courses_tags 中间表,包含 course_idtag_id 列。使用 INSERT IGNORE 防止重复。

# 创建带标签的课程
curl -X POST http://localhost:9898/api/v1/cms/courses \
  -d '{"title":"Rust 入门","tags":["<tag_id_1>","<tag_id_2>"]}'

One To One(一对一)

单条关联记录 — 外键在源表中。

# 每个用户有一个档案
[[fields]]
name = "profile"
field_type = "relation"
relation = { relation_type = "one_to_one", target = "profiles" }

One Way(单向引用)

单向引用 — 类似 many_to_one,但目标侧不会创建反向关联。

# 书签引用文章,但文章不知道有哪些书签
[[fields]]
name = "article_ref"
field_type = "relation"
relation = { relation_type = "one_way", target = "articles" }

Many Way(单向多对多)

通过中间表的单向多关联 — 目标侧无反向引用。

[[fields]]
name = "recommended"
field_type = "relation"
relation = { relation_type = "many_way", target = "courses", through = "course_recommendations" }

关联配置选项

[[fields]]
name = "author"
field_type = "relation"
relation = { relation_type = "many_to_one", target = "users", foreign_key = "author_id" }
required = true
选项必填默认值说明
relation_type6 种类型之一
target目标表名
foreign_key{field_name}_id自定义外键列名
through{source}_{target}中间表名(M2M / ManyWay)

此外,required = true 会使外键列为 NOT NULL

用 include 填充关联

默认情况下,关联字段返回 ID。使用 include 参数将它们展开为完整记录:

# 填充单个关联
curl http://localhost:9898/api/v1/cms/courses?include=instructor

# 填充多个关联
curl http://localhost:9898/api/v1/cms/courses?include=instructor,tags

# 嵌套填充 — 课程中填充课时
curl http://localhost:9898/api/v1/cms/courses?include=instructor,lessons,tags

使用 include 的响应:

{
  "id": "abc123",
  "title": "Rust 入门",
  "instructor": {
    "id": "xyz789",
    "name": "Alice"
  },
  "tags": [
    { "id": "t1", "name": "Rust" },
    { "id": "t2", "name": "编程" }
  ]
}

不带 include 时,同一请求返回:

{
  "id": "abc123",
  "title": "Rust 入门",
  "instructor": "xyz789",
  "tags": ["t1", "t2"]
}

按关联过滤

使用 {field_name}_id 按关联过滤:

# 查询某讲师的所有课程
curl "http://localhost:9898/api/v1/cms/courses?instructor_id=xyz789"

# 查询某课程的所有课时
curl "http://localhost:9898/api/v1/cms/lessons?course_id=abc123"

中间表自动清理

删除记录时,ManyToMany / ManyWay 的中间表行会自动移除,不会产生孤立引用。

最佳实践

  1. 双向定义关联 — 例如 Course → Instructor 用 many_to_one,Instructor → Courses 用 one_to_many。这样才能双向 include
  2. 让系统自动命名中间表 — 除非需要特定名称,否则省略 through;默认的 {source}_{target} 命名约定清晰一致。
  3. 使用 one_way / many_way — 当目标内容类型不需要反向链接时(如活动日志、审计引用)。

On this page