Tube - Studio Videos

Database - Foreign keys 外键
  • 外键就是在一张表里,存放另一张表主键的字段,用来建立表与表之间的约束和联系
  • 外键是数据库级别的约束,当前例子中,如果用户注销,也就是users.id被删除,那么该用户下的发布的视频都会被删除
  • 外键与 relations 功能类似,但作用级别不同
css 复制代码
export const videos = pgTable("videos", {
  ...
  userId: uuid("user_id").references(() => users.id, { // 外键 - 关联到users表的id字段
    onDelete: "cascade", // 级联删除,如果用户被删除,则删除该用户的所有视频
  }).notNull(),
  categoryId: uuid("category_id").references(() => categories.id, {
    onDelete: "set null", // 级联删除,如果分类被删除,则将视频的分类设置为null,但不删除视频
  }),
  ...
})
Database - Relations 关系
  • 关于relations与foreign key之间的解释,请参考 Drizzle soft relations
  • 表与表之间的逻辑联系,是业务逻辑层面的概念
  • 关系型数据库中常见的关系:One-to-One,One-to-Many,Many-to-Many
  • 视频与用户一对一,视频对应视频分类也是一对一
less 复制代码
export const videoRelations = relations(videos, ({ one }) => ({
  user: one(users, {
    fields: [videos.userId],
    references: [users.id],
  }),
  category: one(categories, {
    fields: [videos.categoryId],
    references: [categories.id],
  }),
}))
  • 用户与视频一对多,或者用户视频为空(不传fields、references)
javascript 复制代码
export const usersRelations = relations(users, ({ many }) => ({
  videos: many(videos), // 一对多关系,用户可以有多个视频,或者为空
}));
Cursor-based pagination 游标分页
  • 我们在获取videos数据的时候,考虑到页面是无限加载滚动的,因此这个tRPC路由使用游标分页
  • 用一个锚点(例如上一条记录的id或时间戳)作为起点,往后取数据;需要记住最后一条记录来精准获取下一页数据
  • 输入参数有2个:cursorlimit
css 复制代码
getAll: protectedProcedure
  .input(
    z.object({
      // 可选游标参数,上一次的最后一条数据,首次请求可不传
      cursor: z.object({ 
          id: z.uuid(),
          updatedAt: z.date(),
      }).nullish(), 
      // 每页数据条数限制
      limit: z.number().min(1).max(100), 
    })
)
  • 使用 prefetchInfinite() 预取数据:预取只加载第一页的数据,因此不用传 cursor
php 复制代码
void trpc.studio.getAll.prefetchInfinite({
  limit: DEFAULT_LIMIT
});
  • 获取缓存数据时使用 useSuspenseInfiniteQuery()
css 复制代码
const [videos, query] = trpc.studio.getAll.useSuspenseInfiniteQuery(
  { limit: DEFAULT_LIMIT },
  { getNextPageParam: lastPage => lastPage.nextCursor }
)
  • tRPC路由中的Sql查询条件:
    • eq(field, value) 等于,field = value
    • and(cond1, cond2, ...) 且,多个条件同时满足,cond1 and cond2 and ...
    • or(cond1, cond2, ...) 或,多个条件只要一个满足,cond1 or cond2 or ...
    • lt(field, value) 小于,Less Than,field < value
    • desc(field) 倒序排序,DESC,根据field字段倒序排序
javascript 复制代码
import { eq, and, or, lt, desc } from 'drizzle-orm'
kotlin 复制代码
getAll: protectedProcedure
  .input(...)
  .query(async ({ ctx, input }) => {
    const { cursor, limit } = input
    const { id: userId } = ctx.user

    const data = await db
      .select()
      .from(videos)
      .where(
        and(
          eq( videos.userId, userId ),  // 只查询当前用户的视频
          cursor ? or(
            lt(videos.updatedAt, cursor.updatedAt),  // 查询更新时间小于游标参数的记录
            and(
              eq(videos.updatedAt, cursor.updatedAt),  // 如果更新时间相同,则查询id小于游标参数的记录
              lt(videos.id, cursor.id)
            )
          ) : undefined
        )
      )
      .orderBy(desc(videos.updatedAt), desc(videos.id))  // 按更新时间和ID降序排列,也就是最新的视频在前面
      .limit(limit + 1)  // 多查询一条数据用于判断是否还有下一页

      const hasMore = data.length > limit // 判断是否还有下一页
      const videosData = hasMore ? data.slice(0, -1) : data // 如果还有下一页,则去掉最后一条数据
      const lastVideo = videosData[videosData.length - 1] // 获取最后一条数据,用于生成下一页的游标
      // 生成下一页的cursor
      const nextCursor = hasMore ? { 
        id: lastVideo.id,
        updatedAt: lastVideo.updatedAt,
      } : null

    return {
      videosData,
      nextCursor, // 是一个对象,包含了id和updatedAt两个字段
    }
  })
相关推荐
枕星而眠3 分钟前
Linux守护进程完全指南:从原理到实战
linux·运维·服务器·c++·后端
云水一下19 分钟前
Vue.js从零到精通系列(三):组件化基础——Props、Emits、插槽与生命周期
前端·javascript·vue.js
SEO_juper1 小时前
新独立站冷启动收录全攻略:配置、推送、抓取配额优化完整手册
前端·谷歌·seo·跨境电商·外贸·geo·独立站
TinssonTai1 小时前
这个 VS Code 插件让我的 AI Coding 又快又稳 - 旧瓶装新酒
前端·人工智能·程序员
体验家1 小时前
体验家 XMPlus 网页端问卷 SDK 技术解析:用几行 JavaScript 实现精准场景触发与防打扰机制
开发语言·前端·javascript
金融支付架构实战指南1 小时前
Milvus 向量检索服务 + SpringBoot 实战:电商商品语义检索与相似商品推荐
spring boot·后端·milvus·向量检索
Maimai108081 小时前
Web3 前端交易系统如何落地:从下单 UI 到 Operation 编码、签名与实时状态更新
前端·react.js·ui·架构·前端框架·web3
齐 飞1 小时前
JDK21虚拟线程
java·后端
kidding7231 小时前
高效备忘清单工具类小程序
前端·计算机网络·微信小程序·小程序
fox_lht1 小时前
15.4.循环和迭代器的性能比较
开发语言·后端·学习·rust