PolarDB Supabase最佳实践-Web应用

本文涉及的产品
RDS MySQL DuckDB 分析主实例,集群系列 4核8GB
RDS AI 助手,专业版
简介: PolarDB Supabase 是基于 PolarDB PostgreSQL 版的全托管服务,集成 Realtime 实时数据库、RESTful API、身份认证、文件存储等功能,提供高性能、灵活扩展的后端解决方案。用户可快速构建 Web 应用、SaaS 平台及 AI 集成应用,简化运维操作,提升开发效率。

PolarDB SupabasePolarDB PostgreSQL版推出全托管的Supabase服务,以PolarDB PostgreSQL版为核心,整合了Realtime实时数据库、RESTful API、GoTrue身份认证、文件存储、日志采集等关键功能,并在此基础上进行了优化与增强,为您省去Supabase复杂的参数管理和应用运维等操作,并提供了兼具灵活性与高性能的后端解决方案。您可以基于PolarDB Supabase快速搭建Web、SaaS平台、AI集成应用等现代化应用。

接下来,将为您展示如何使用PolarDB Supabase快速搭建一个会议笔记系统。

效果展示

交互体验如下,打开两个浏览器,进入同一个会议,可以观察到两侧的信息是实时同步的。会议笔记系统的核心功能包括实时协作编辑、用户在线状态管理、文件上传与管理、任务追踪、活动日志以及标签系统。

核心功能

完整数据库功能

Supabase基于PolarDB PostgreSQL版数据库构建,提供完整的数据库功能:

  • 关系型数据库: 支持复杂的表关系、外键约束、事务处理。
  • JSONB支持: 存储半结构化数据,如笔记内容、活动数据。
  • 全文搜索: 内置全文搜索功能。
  • 扩展支持: 支持PostgreSQL扩展,如UUID生成、时间戳处理。
-- 示例:使用JSONB存储复杂数据
CREATE TABLE notes (
  id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
  content JSONB DEFAULT '{}',  -- 存储富文本内容
  activity_data JSONB DEFAULT '{}'  -- 存储活动元数据
);

实时订阅(Realtime)

基于PostgreSQL的逻辑复制,实现实时数据同步:

  • 数据库变更监听: 监听INSERT、UPDATE、DELETE事件。
  • 频道管理: 支持多个独立频道,按需订阅。
  • 事件过滤: 通过条件过滤减少不必要的事件。
  • 自动重连: 网络断开时自动重连。
// 实时订阅示例
const channel = supabase
  .channel('meeting-updates')
  .on('postgres_changes', {
    event: 'UPDATE',
    schema: 'public',
    table: 'notes',
    filter: 'meeting_id=eq.123'
  }, (payload) => {
    console.log('笔记已更新:', payload.new)
  })
  .subscribe()

身份认证(Auth)

内置完善的身份认证和授权系统:

  • 多种登录方式: 邮箱密码、社交登录、魔法链接。
  • 会话管理: 自动处理token刷新、会话持久化。
  • 用户管理: 用户注册、密码重置、邮箱验证。
  • 匿名用户: 支持临时用户访问。
// 认证示例
const { data: { user }, error } = await supabase.auth.signInWithPassword({
  email: 'user@example.com',
  password: 'password'
})

行级安全(RLS)

基于PostgreSQL的行级安全策略:

  • 细粒度权限控制: 基于用户、角色、数据条件控制访问。
  • 策略定义: 使用SQL定义访问规则。
  • 自动应用: 所有查询自动应用安全策略。
  • 性能优化: 在数据库层面过滤数据。
-- RLS策略示例
CREATE POLICY "Users can only see their own meetings" ON meetings
  FOR SELECT USING (auth.uid() = created_by);

CREATE POLICY "Users can update their own meetings" ON meetings
  FOR UPDATE USING (auth.uid() = created_by);

存储服务(PolarFS)

基于PolarDB文件系统(Polar File System,简称PolarFS)进行文件存储与管理:

  • 文件上传: 支持大文件上传、断点续传。
  • 访问控制: 基于RLS的文件访问权限。
  • 文件管理: 文件夹组织、元数据管理。
// 文件上传示例
const { data, error } = await supabase.storage
  .from('meeting-files')
  .upload('document.pdf', file, {
    cacheControl: '3600',
    upsert: false
  })

边缘函数(Edge Functions)

基于Deno的服务器端函数:

  • TypeScript支持: 原生TypeScript支持。
  • 数据库访问: 直接访问Supabase数据库。
  • 第三方集成: 调用外部API、处理webhook。
// 边缘函数示例
import { serve } from "https://deno.land/std@0.168.0/http/server.ts"
import { createClient } from 'https://esm.sh/@supabase/supabase-js@2'

serve(async (req) => {
  const supabase = createClient(
    Deno.env.get('SUPABASE_URL') ?? '',
    Deno.env.get('SUPABASE_ANON_KEY') ?? ''
  )
  
  const { data } = await supabase.from('meetings').select('*')
  return new Response(JSON.stringify(data), {
    headers: { 'Content-Type': 'application/json' }
  })
})

API(REST & GraphQL)

自动生成的API接口:

  • REST API: 自动生成CRUD接口。
  • GraphQL: 支持GraphQL查询(企业版)。
  • 实时API: 支持实时查询和订阅。
  • 类型安全: TypeScript类型。
// REST API示例
const { data, error } = await supabase
  .from('meetings')
  .select('*, notes(*)')
  .eq('id', meetingId)
  .single()

搭建会议笔记系统

在会议笔记系统中,将主要应用以下功能:

功能

说明

PolarDB PostgreSQL版集群

数据存储,主要记录会议、笔记、任务、用户状态等表信息。

实时订阅(Realtime)

协作功能,用于实时同步笔记编辑、用户在线状态。

行级安全(RLS)

数据安全,用于控制用户访问权限。

存储服务(PolarFS)

文件管理,用于会议资料上传和下载。

身份认证(Auth)

用户管理,用于管理用户登录和会话管理。

应用技术栈

  • 前端:Next.js 15 + React 18 + TypeScript。
  • 后端PolarDB Supabase (PostgreSQL + 鉴权 + 实时订阅 + 存储)。
  • UI:Tailwind CSS + Radix UI。
  • 状态管理:React Hooks + 本地状态。

数据库设计

为会议笔记系统的核心功能设计会议表、笔记表、用户在线状态表、标签表及任务表等系统表,并通过外键约束以确保数据的一致性。

SQL示例:

-- 创建会议表
CREATE TABLE IF NOT EXISTS meetings (
  id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
  title VARCHAR(255) NOT NULL,
  description TEXT,
  created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
  updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);

-- 创建笔记表
CREATE TABLE IF NOT EXISTS notes (
  id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
  meeting_id UUID REFERENCES meetings(id) ON DELETE CASCADE,
  content JSONB DEFAULT '{}',
  created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
  updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);

-- 创建用户在线状态表
CREATE TABLE IF NOT EXISTS user_presence (
  id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
  meeting_id UUID REFERENCES meetings(id) ON DELETE CASCADE,
  user_name VARCHAR(100) NOT NULL,
  user_color VARCHAR(7) DEFAULT '#1890ff',
  is_typing BOOLEAN DEFAULT FALSE,
  last_seen TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
  created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
  UNIQUE(meeting_id, user_name)
);

-- 创建标签表
CREATE TABLE IF NOT EXISTS tags (
  id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
  meeting_id UUID REFERENCES meetings(id) ON DELETE CASCADE,
  name VARCHAR(50) NOT NULL,
  color VARCHAR(7) DEFAULT '#1890ff',
  created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);

-- 创建任务表
CREATE TABLE IF NOT EXISTS tasks (
  id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
  meeting_id UUID REFERENCES meetings(id) ON DELETE CASCADE,
  title VARCHAR(255) NOT NULL,
  description TEXT,
  assignee VARCHAR(100),
  status VARCHAR(20) DEFAULT 'pending',
  due_date TIMESTAMP WITH TIME ZONE,
  created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
  updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);

-- 创建会议活动日志表
CREATE TABLE IF NOT EXISTS meeting_activities (
  id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
  meeting_id UUID REFERENCES meetings(id) ON DELETE CASCADE,
  user_name VARCHAR(100) NOT NULL,
  activity_type VARCHAR(50) NOT NULL, -- 'join', 'leave', 'edit', 'add_tag', 'add_task', etc.
  activity_data JSONB DEFAULT '{}',
  created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);

-- 会议资料表:meeting_files
CREATE TABLE IF NOT EXISTS meeting_files (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  meeting_id UUID REFERENCES meetings(id) ON DELETE CASCADE,
  file_name VARCHAR(255) NOT NULL,
  file_url TEXT NOT NULL,
  uploader VARCHAR(100),
  uploaded_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
  file_size BIGINT,
  mime_type VARCHAR(100)
);

-- 为会议ID加索引
CREATE INDEX IF NOT EXISTS idx_meeting_files_meeting_id ON meeting_files(meeting_id);

实时订阅配置

启用实时功能

-- 启用实时订阅功能
ALTER PUBLICATION supabase_realtime ADD TABLE meetings;
ALTER PUBLICATION supabase_realtime ADD TABLE notes;
ALTER PUBLICATION supabase_realtime ADD TABLE user_presence;
ALTER PUBLICATION supabase_realtime ADD TABLE tags;
ALTER PUBLICATION supabase_realtime ADD TABLE tasks;
ALTER PUBLICATION supabase_realtime ADD TABLE meeting_activities;
ALTER PUBLICATION supabase_realtime ADD TABLE meeting_files; 

客户端实时订阅

// 创建自定义Hook管理实时订阅
export function useRealtime(meetingId: string, callbacks: RealtimeCallbacks) {

  const channelsRef = useRef<any[ ]>([ ])


  const cleanup = useCallback(() => {
    channelsRef.current.forEach((channel) => {
      supabase.removeChannel(channel)
    })
    channelsRef.current = []
  }, [])


  useEffect(() => {
    if (!meetingId) return

    // 清理之前的连接
    cleanup()

    // 创建多个专用频道
    const presenceChannel = supabase
      .channel(`presence:${meetingId}`)
      .on(
        "postgres_changes",
        {
          event: "*",
          schema: "public",
          table: "user_presence",
          filter: `meeting_id=eq.${meetingId}`,
        },
        (payload) => {
          console.log("User presence change:", payload)
          if (callbacks.onUserPresenceChange) {
            loadOnlineUsers()
          }
        },
      )
      .subscribe()

    // 保存频道引用用于清理
    channelsRef.current = [presenceChannel, /* 其他频道 */]
  }, [meetingId, callbacks])

  return { cleanup }
}

实时订阅设计指南

  • 功能隔离:按业务场景划分独立频道(如在线状态、文档协作、任务通知),避免逻辑耦合。
  • 事件过滤:通过filter参数限定事件范围(如指定会议ID),减少冗余数据传输。
  • 资源回收:在组件卸载或页面跳转时,主动调用removeChannel清理所有频道连接,释放资源。
  • 错误处理:监听订阅通道的状态,对断连、超时等异常进行重试或降级处理。

安全性

行级安全(RLS)

-- 启用RLS
ALTER TABLE meetings ENABLE ROW LEVEL SECURITY;

-- 创建安全策略
CREATE POLICY "Users can view all meetings" ON meetings
  FOR SELECT USING (true);

CREATE POLICY "Users can create meetings" ON meetings
  FOR INSERT WITH CHECK (true);

CREATE POLICY "Users can update their own meetings" ON meetings
  FOR UPDATE USING (auth.uid() = created_by);

用户认证

  const login = useCallback(async (email: string, password: string) => {
    try {
      const { data, error } = await supabase.auth.signInWithPassword({ email, password })
      if (error) throw error
      if (data.user) {
        const userData = transformSupabaseUser(data.user)
        setUser(userData)
        localStorage.setItem("meeting_user", JSON.stringify(userData))
        return { success: true, user: userData }
      }
      return { success: false, error: '登录失败' }
    } catch (error: any) {
      return { success: false, error: error.message || '登录失败' }
    }
  }, [])

  const transformSupabaseUser = (supabaseUser: SupabaseUser): User => ({
    id: supabaseUser.id,
    email: supabaseUser.email || null,
    name: supabaseUser.user_metadata?.name || supabaseUser.email?.split('@')[0] || '用户',
    avatar_url: supabaseUser.user_metadata?.avatar_url || null,
    created_at: supabaseUser.created_at,
    is_anonymous: supabaseUser.user_metadata?.is_anonymous || false,
  })

客户端集成

客户端配置

// lib/supabase.ts
import { createClient } from '@supabase/supabase-js'

const supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL!
const supabaseAnonKey = process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!

export const supabase = createClient(supabaseUrl, supabaseAnonKey)

// 类型定义
export interface Meeting {
  id: string
  created_at: string
  title: string
  description: string | null
}

环境变量管理

# 生产环境变量
NEXT_PUBLIC_SUPABASE_URL=<YOUR_SUPABASE_PUBLIC_URL>
NEXT_PUBLIC_SUPABASE_ANON_KEY=<YOUR_SUPABASE_ANON_KEY>

快速搭建

  1. 下载项目示例代码PolarDB-Supabase-App-Demo
  2. 环境配置:在项目根目录创建.env.local文件,并将以下值替换为您PolarDB Supabase的配置。

说明

您可在集群的AI能力 > AI应用列表页面,单击您的应用ID进入应用详情页,在拓扑图配置页签中查看相关配置信息。

  • <YOUR_SUPABASE_PUBLIC_URL>为集群公网地址
  • <YOUR_SUPABASE_ANON_KEY>为集群参数secret.jwt.anonKey的值。
# 生产环境变量
NEXT_PUBLIC_SUPABASE_URL=<YOUR_SUPABASE_PUBLIC_URL>
NEXT_PUBLIC_SUPABASE_ANON_KEY=<YOUR_SUPABASE_ANON_KEY>
  1. 数据库初始化:在项目根目录的scripts文件夹下找到01-create-tables.sql文件,并在Supabase Dashboard上面的右侧导航栏SQL Editor中执行SQL。

  1. 运行项目:在项目根目录执行如下命令。运行功能后,默认本地访问地址为http://localhost:3000,您可直接在浏览器中访问系统。

说明

在运行项目之前,请确保在您的本地环境中已安装Node.jspnpm

  • Node.js:请前往Node.js官方网站进行下载和安装。
  • pnpm:在安装Node.js后,可通过npm进行全局安装,命令为npm install -g pnpm
pnpm install
pnpm dev

经验总结

基于上述会议笔记系统项目的实战经验,PolarDB Supabase最佳实践包括:

遵循这些最佳实践可以构建稳定、安全、高性能的PolarDB Supabase应用。

相关实践学习
使用PolarDB和ECS搭建门户网站
本场景主要介绍如何基于PolarDB和ECS实现搭建门户网站。
阿里云数据库产品家族及特性
阿里云智能数据库产品团队一直致力于不断健全产品体系,提升产品性能,打磨产品功能,从而帮助客户实现更加极致的弹性能力、具备更强的扩展能力、并利用云设施进一步降低企业成本。以云原生+分布式为核心技术抓手,打造以自研的在线事务型(OLTP)数据库Polar DB和在线分析型(OLAP)数据库Analytic DB为代表的新一代企业级云原生数据库产品体系, 结合NoSQL数据库、数据库生态工具、云原生智能化数据库管控平台,为阿里巴巴经济体以及各个行业的企业客户和开发者提供从公共云到混合云再到私有云的完整解决方案,提供基于云基础设施进行数据从处理、到存储、再到计算与分析的一体化解决方案。本节课带你了解阿里云数据库产品家族及特性。
相关文章
|
5月前
|
边缘计算 关系型数据库 分布式数据库
PolarDB Supabase Edge Functions - 让函数,随时可用
PolarDB Supabase Edge Functions 是现代全栈开发的无服务器引擎,基于 Deno 运行时构建,支持在全球边缘节点部署自定义代码,实现低延迟、高可用的 API 与事件处理。它提供 CLI 和可视化 Studio 两种开发方式,打造高效开发闭环。相比开源版 Supabase,PolarDB Supabase 在公有云环境中实现了完整功能闭环,兼顾企业级控制力与便捷开发体验。
PolarDB Supabase Edge Functions - 让函数,随时可用
|
6月前
|
人工智能 关系型数据库 分布式数据库
PolarDB Supabase 助力快速构建现代应用
简介:本文介绍了在AI时代背景下,如何通过阿里云瑶池推出的全托管Supabase服务快速构建现代应用。该服务基于开源Supabase与PolarDB-PG数据库,提供一站式后端解决方案,涵盖实时数据库、身份认证、文件存储及AI能力,助力开发者高效迭代业务,降低运维复杂度。适用于协作类应用、SaaS平台、移动开发等多种场景。
|
存储 关系型数据库 分布式数据库
GraphRAG:基于PolarDB+通义千问+LangChain的知识图谱+大模型最佳实践
本文介绍了如何使用PolarDB、通义千问和LangChain搭建GraphRAG系统,结合知识图谱和向量检索提升问答质量。通过实例展示了单独使用向量检索和图检索的局限性,并通过图+向量联合搜索增强了问答准确性。PolarDB支持AGE图引擎和pgvector插件,实现图数据和向量数据的统一存储与检索,提升了RAG系统的性能和效果。
|
Web App开发 编解码 vr&ar
使用Web浏览器访问UE应用的最佳实践
在3D/XR应用开发中,尤其是基于UE(虚幻引擎)开发的高精度场景,传统终端因硬件局限难以流畅运行高帧率、复杂效果的三维应用。实时云渲染技术,将渲染任务转移至云端服务器,降低终端硬件要求,确保用户获得流畅体验。具备弹性扩展、优化传输协议、跨平台支持和安全性等优势,适用于多种终端和场景,特别集成像素流送技术,帮助UE开发者实现低代码上云操作,简化部署流程,保留UE引擎的强大开发能力,确保画面精美且终端轻量化。
548 17
使用Web浏览器访问UE应用的最佳实践
|
NoSQL 关系型数据库 MySQL
阿里云PolarDB游戏场景最佳实践
阿里云PolarDB游戏场景最佳实践涵盖了数据库体系演进、行业优化、Redis解决方案、性能优化、备份还原及全球部署等内容。PolarDB通过共享存储、物理复制等技术提升读扩展和大容量支持,针对游戏行业的高IO需求进行优化,提供秒级备份与快速恢复能力。同时,PolarDB for Redis实现了一写多读架构,支持百TB级别的高性能存储,具备成本优势。该方案已在米哈游等大型游戏中广泛应用,确保了高并发下的稳定性和数据一致性,满足游戏行业的特殊需求。
606 36
|
人工智能 关系型数据库 分布式数据库
PolarDB-PG AI最佳实践3 :PolarDB AI多模态相似性搜索最佳实践
本文介绍了如何利用PolarDB结合多模态大模型(如CLIP)实现数据库内的多模态数据分析和查询。通过POLAR_AI插件,可以直接在数据库中调用AI模型服务,无需移动数据或额外的工具,简化了多模态数据的处理流程。具体应用场景包括图像识别与分类、图像到文本检索和基于文本的图像检索。文章详细说明了技术实现、配置建议、实战步骤及多模态检索示例,展示了如何在PolarDB中创建模型、生成embedding并进行相似性检索
|
SQL 人工智能 关系型数据库
PolarDB-PG AI最佳实践 2 :PolarDB AI X EAS实现自定义库内模型推理最佳实践
PolarDB通过POLAR_AI插件支持使用SQL调用AI/ML模型,无需专业AI知识或额外部署环境。结合阿里云EAS在线模型服务,可轻松部署自定义模型,在SQL中实现如文本翻译等功能。

相关产品

  • 云原生数据库 PolarDB