You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Prisma查询分页在结果末尾出现异常问题排查

Prisma分页异常:接近末尾时结果数量逐页递减的原因与修复

问题原因分析

你遇到的分页异常由两个核心问题导致:

1. 关联查询的Where条件写法错误

你的where条件中直接使用clients: { user_email: ctx.session.user.email },在Prisma中这会被解析为:匹配所有关联clients的user_email都等于当前用户的subscription。但实际场景中,你需要的是找存在至少一个关联clients的user_email等于当前用户的subscription,这种情况下必须使用some操作符。

错误的过滤条件会大幅减少符合预期的结果数量,导致实际数据集规模和你预期的不符,进而引发分页结果异常。

2. 分页偏移量计算错误

当前代码中skip: input.pageIndex直接将页码作为偏移量,正确的偏移量应该是页码 × 每页数量(即input.pageIndex * input.pageSize)。错误的偏移量计算会导致每次只跳过少量条目而非整页,最终出现逐页递减的结果数量。

修复方案

修改Prisma查询代码,同时修正Where条件和偏移量计算:

get: protectedProcedure
    .input(
      z.object({
        pageSize: z.number().min(1).max(100),
        pageIndex: z.number().min(0),
      })
    )
    .query(async ({ input, ctx }) => {
      return await prisma.subscription.findMany({
        where: {
          // 修正关联查询条件:匹配至少一个符合条件的client
          clients: {
            some: {
              user_email: ctx.session.user.email,
            },
          },
        },
        include: {
          lines: {
            select: {
              phone_number: true,
              sim_number: true,
              sim_status: true,
            },
          },
        },
        take: input.pageSize,
        // 修正偏移量计算:页码 × 每页数量
        skip: input.pageIndex * input.pageSize,
      });
    }),

额外优化建议

为避免大数据量下的分页性能问题,可做以下优化:

  • 为subscription与clients的关联字段、user_email字段创建索引,提升查询效率。
  • 考虑使用游标分页替代偏移量分页,避免skip在大数据量下的性能损耗。示例如下:
// 基于自增id的游标分页示例
get: protectedProcedure
    .input(
      z.object({
        pageSize: z.number().min(1).max(100),
        cursor: z.string().nullish(), // 上一页最后一条数据的id
      })
    )
    .query(async ({ input, ctx }) => {
      const subscriptions = await prisma.subscription.findMany({
        where: {
          clients: {
            some: {
              user_email: ctx.session.user.email,
            },
          },
          ...(input.cursor && { id: { gt: input.cursor } }),
        },
        include: {
          lines: {
            select: {
              phone_number: true,
              sim_number: true,
              sim_status: true,
            },
          },
        },
        take: input.pageSize + 1, // 多取一条判断是否还有下一页
        orderBy: { id: 'asc' },
      });

      const hasNextPage = subscriptions.length > input.pageSize;
      const nextCursor = hasNextPage ? subscriptions[subscriptions.length - 1].id : null;

      return {
        data: hasNextPage ? subscriptions.slice(0, -1) : subscriptions,
        nextCursor,
        hasNextPage,
      };
    }),

内容的提问来源于stack exchange,提问作者Mendy Landa

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 02:40:40