Supabase PG_GraphQL 技术解析:从SQL表到GraphQL API的自动映射
pg_graphql GraphQL support for PostgreSQL 项目地址: https://gitcode.com/gh_mirrors/pg/pg_graphql
概述
Supabase PG_GraphQL 是一个强大的工具,它能够自动将PostgreSQL数据库表结构映射为GraphQL API。本文将深入解析这一映射过程的核心机制,帮助开发者理解如何通过GraphQL高效地操作PostgreSQL数据库。
基础映射原理
表到类型的转换
PG_GraphQL的核心功能是将SQL表自动转换为GraphQL类型:
- 表名映射:每个PostgreSQL表都会生成对应的GraphQL类型,默认情况下表名直接转换为类型名(如
account_holder
表对应account_holder
类型) - 字段映射:表中的列和关系(外键)会转换为类型的字段
对于使用snake_case命名规范的SQL实体,可以启用名称转换功能,将表名和字段名转换为更符合GraphQL/JavaScript的命名风格(如account_holder
→ AccountHolder
)
主键要求
每个表必须定义主键才能暴露在GraphQL模式中。例如:
-- 会被暴露,因为有主键
create table "Blog"(
id serial primary key,
name varchar(255) not null
);
-- 不会被暴露,因为没有主键
create table "BlogNoPK"(
id int,
name varchar(255) not null
);
查询类型详解
Node接口
node
接口是GraphQL API的重要入口点,它允许通过全局唯一的nodeId
字段检索记录:
type Query {
node(nodeId: ID!): Node
}
使用示例:
{
node(nodeId: "WyJwdWJsaWMiLCAiYmxvZyIsIDFd") {
nodeId
... on Blog {
name
description
}
}
}
集合查询
每个表都会在Query类型中生成对应的集合查询入口:
type Query {
blogCollection(
first: Int
last: Int
before: Cursor
after: Cursor
offset: Int
filter: BlogFilter
orderBy: [BlogOrderBy!]
): BlogConnection
}
集合查询返回连接类型(Connection),支持分页、过滤和排序。
连接类型结构
type BlogConnection {
totalCount: Int! # 匹配过滤条件的记录总数
pageInfo: PageInfo! # 分页元数据
edges: [BlogEdge!]! # 结果集
aggregate: BlogAggregate # 聚合函数结果
}
type BlogEdge {
cursor: String! # 记录的唯一标识符
node: Blog # 记录内容
}
type PageInfo {
startCursor: String
endCursor: String
hasNextPage: Boolean!
hasPreviousPage: Boolean!
}
高级查询功能
聚合函数
聚合功能可以对匹配查询条件的记录集合进行统计计算:
type BlogAggregate {
count: Int! # 记录计数
sum: BlogSumAggregateResult # 求和
avg: BlogAvgAggregateResult # 平均值
min: BlogMinAggregateResult # 最小值
max: BlogMaxAggregateResult # 最大值
}
使用示例:
{
blogCollection(filter: {rating: {gt: 3}}) {
aggregate {
count
sum { rating visits }
avg { rating }
min { createdAt title }
max { rating updatedAt }
}
}
}
分页机制
PG_GraphQL支持两种分页方式:
1. 基于游标的分页
遵循Relay规范,使用first
/last
和after
/before
参数:
{
blogCollection(
first: 2,
after: "WzJd" # 上一页的endCursor
) {
pageInfo {
hasNextPage
endCursor
}
edges {
node { id name }
}
}
}
2. 基于偏移量的分页
使用first
和offset
参数,类似于SQL的LIMIT和OFFSET:
{
blogCollection(
first: 2,
offset: 2
) {
edges {
node { id name }
}
}
}
注意:偏移量分页在大偏移量时性能较差,推荐优先使用游标分页。
过滤功能
通过filter
参数可以对结果集进行筛选:
input BlogFilter {
id: IntFilter
name: StringFilter
description: StringFilter
tags: StringListFilter
createdAt: DatetimeFilter
and: [BlogFilter!]
or: [BlogFilter!]
not: BlogFilter
}
支持多种过滤操作符:
| 操作符 | 描述 | 适用类型 | |------------|-----------------------------|---------------------| | eq | 等于 | 所有类型 | | neq | 不等于 | 所有类型 | | gt/gte | 大于/大于等于 | 数值、字符串、日期时间 | | lt/lte | 小于/小于等于 | 数值、字符串、日期时间 | | in | 在值列表中 | 所有类型 | | is | 是NULL/NOT NULL | 所有类型 | | startsWith | 以指定字符串开头 | 字符串 | | like/ilike | 模式匹配(区分/不区分大小写) | 字符串 | | regex | 正则表达式匹配 | 字符串 | | contains | 包含(用于数组列) | 数组类型 |
使用示例:
{
blogCollection(
filter: {
rating: { gt: 3 },
or: [
{ name: { ilike: "%graphql%" } },
{ tags: { contains: ["database"] } }
]
}
) {
edges {
node { id name rating }
}
}
}
总结
Supabase PG_GraphQL提供了从PostgreSQL到GraphQL的完整映射方案,包括:
- 自动类型生成:将表结构转换为GraphQL类型
- 丰富的查询功能:支持节点查询、集合查询
- 高级数据操作:聚合、分页、过滤等
- 灵活的命名控制:支持名称转换和手动覆盖
这些特性使得开发者能够以GraphQL的方式高效地操作PostgreSQL数据库,同时保持对数据模型的完全控制。
pg_graphql GraphQL support for PostgreSQL 项目地址: https://gitcode.com/gh_mirrors/pg/pg_graphql
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考