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
相关产品推荐
相关产品推荐

