查询关联表与嵌套表
数据API会自动检测Postgres表之间的关系。由于Postgres是一个关系型数据库,这是非常常见的情况。
一对多关联
让我们使用一个存储orchestral_sections
(乐团声部)和instruments
(乐器)的示例数据库:
乐团声部
id | name |
---|---|
1 | 弦乐组 |
2 | 木管组 |
乐器
id | name | section_id |
---|---|---|
1 | 小提琴 | 1 |
2 | 中提琴 | 1 |
3 | 长笛 | 2 |
4 | 双簧管 | 2 |
API会根据外键自动检测表之间的关系:
12345const { data, error } = await supabase.from('orchestral_sections').select(` id, name, instruments ( id, name )`)
用于联表查询的 TypeScript 类型
supabase-js
总是返回一个 data
对象(表示成功请求)和一个 error
对象(表示失败请求)。
这些辅助类型提供了任何查询的结果类型,包括数据库联表查询的嵌套类型。
给定以下包含管弦乐声部与乐器关系的数据库模式:
12345678910create table orchestral_sections ( "id" serial primary key, "name" text);create table instruments ( "id" serial primary key, "name" text, "section_id" int references "orchestral_sections");
我们可以像这样获取嵌套的 SectionsWithInstruments
类型:
123456789101112131415import { QueryResult, QueryData, QueryError } from '@supabase/supabase-js'const sectionsWithInstrumentsQuery = supabase.from('orchestral_sections').select(` id, name, instruments ( id, name )`)type SectionsWithInstruments = QueryData<typeof sectionsWithInstrumentsQuery>const { data, error } = await sectionsWithInstrumentsQueryif (error) throw errorconst sectionsWithInstruments: SectionsWithInstruments = data
多对多关联
数据API会自动检测多对多关联关系。例如,如果您有一个存储用户团队关系的数据库(每个用户可以属于多个团队):
123456789101112131415create table users ( "id" serial primary key, "name" text);create table teams ( "id" serial primary key, "team_name" text);create table members ( "user_id" int references users, "team_id" int references teams, primary key (user_id, team_id));
在这种情况下,您不需要显式定义连接表(members)。如果我们想获取所有团队及其成员:
12345const { data, error } = await supabase.from('teams').select(` id, team_name, users ( id, name )`)
为多外键连接指定 ON
子句
例如,如果您有一个记录员工上下班打卡的项目:
123456789101112131415161718192021-- 员工表create table users ( "id" serial primary key, "name" text);-- 工牌扫描记录create table scans ( "id" serial primary key, "user_id" int references users, "badge_scan_time" timestamp);-- 工作班次create table shifts ( "id" serial primary key, "user_id" int references users, "scan_id_start" int references scans, -- 上班打卡 "scan_id_end" int references scans, -- 下班打卡 "attendance_status" text);
这种情况下,您需要明确定义连接条件,因为 shifts
表上的连接列存在歧义(它们都引用了 scans
表)。
要获取所有与特定 scan
相关的 shifts
记录(包含 scan_id_start
和 scan_id_end
),请使用以下语法:
123456789101112131415const { data, error } = await supabase.from('shifts').select( ` *, start_scan:scans!scan_id_start ( id, user_id, badge_scan_time ), end_scan:scans!scan_id_end ( id, user_id, badge_scan_time ) `)